base44 0.0.33 → 0.0.35

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/README.md CHANGED
@@ -44,21 +44,22 @@ The CLI will guide you through project setup. For step-by-step tutorials, see th
44
44
  | Command | Description |
45
45
  | ------- | ----------- |
46
46
  | [`create`](https://docs.base44.com/developers/references/cli/commands/create) | Create a new Base44 project from a template |
47
- | [`deploy`](https://docs.base44.com/developers/references/cli/commands/deploy) | Deploy resources and site to Base44 |
48
- | [`link`](https://docs.base44.com/developers/references/cli/commands/link) | Link a local project to a project on Base44 |
47
+ | [`deploy`](https://docs.base44.com/developers/references/cli/commands/deploy) | Deploy all project resources and site to Base44 |
48
+ | [`eject`](https://docs.base44.com/developers/references/cli/commands/eject) | Download the code for an existing Base44 project |
49
+ | [`link`](https://docs.base44.com/developers/references/cli/commands/link) | Link a local project to a Base44 project |
49
50
  | [`dashboard open`](https://docs.base44.com/developers/references/cli/commands/dashboard) | Open the app dashboard in your browser |
50
51
  | [`login`](https://docs.base44.com/developers/references/cli/commands/login) | Authenticate with Base44 |
51
52
  | [`logout`](https://docs.base44.com/developers/references/cli/commands/logout) | Sign out and clear stored credentials |
52
53
  | [`whoami`](https://docs.base44.com/developers/references/cli/commands/whoami) | Display the current authenticated user |
53
54
  | [`agents pull`](https://docs.base44.com/developers/references/cli/commands/agents-pull) | Pull agents from Base44 to local files |
54
55
  | [`agents push`](https://docs.base44.com/developers/references/cli/commands/agents-push) | Push local agents to Base44 |
55
- | [`entities push`](https://docs.base44.com/developers/references/cli/commands/entities-push) | Push local entity schemas to Base44 |
56
+ | [`connectors pull`](https://docs.base44.com/developers/references/cli/commands/connectors-pull) | Pull connectors from Base44 to local files |
57
+ | [`connectors push`](https://docs.base44.com/developers/references/cli/commands/connectors-push) | Push local connectors to Base44 |
58
+ | [`entities push`](https://docs.base44.com/developers/references/cli/commands/entities-push) | Push local entities to Base44 |
56
59
  | [`functions deploy`](https://docs.base44.com/developers/references/cli/commands/functions-deploy) | Deploy local functions to Base44 |
57
60
  | [`site deploy`](https://docs.base44.com/developers/references/cli/commands/site-deploy) | Deploy built site files to Base44 hosting |
58
61
  | [`site open`](https://docs.base44.com/developers/references/cli/commands/site-open) | Open the published site in your browser |
59
-
60
-
61
- <!--| [`eject`](https://docs.base44.com/developers/references/cli/commands/eject) | Create a Base44 backend project from an existing Base44 app | -->
62
+ | [`types generate`](https://docs.base44.com/developers/references/cli/commands/types-generate) | Generate TypeScript types from project resources |
62
63
 
63
64
  ## AI agent skills
64
65
 
@@ -91,4 +92,4 @@ Found a bug? [Open an issue](https://github.com/base44/cli/issues).
91
92
 
92
93
  ## License
93
94
 
94
- ISC
95
+ MIT
package/dist/cli/index.js CHANGED
@@ -1,4 +1,4 @@
1
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._posthogChunkIds=e._posthogChunkIds||{},e._posthogChunkIds[n]="019c751d-ed06-7271-9f3f-d37c42112446")}catch(e){}}();import { createRequire } from "node:module";
1
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._posthogChunkIds=e._posthogChunkIds||{},e._posthogChunkIds[n]="019c8b01-a41e-78d0-855b-1f264ec2d7de")}catch(e){}}();import { createRequire } from "node:module";
2
2
  var __create = Object.create;
3
3
  var __getProtoOf = Object.getPrototypeOf;
4
4
  var __defProp = Object.defineProperty;
@@ -178557,9 +178557,10 @@ class ApiError extends SystemError {
178557
178557
  } catch {
178558
178558
  message = error48.message;
178559
178559
  }
178560
+ const statusCode = ApiError.normalizeStatusCode(error48.response.status, responseBody);
178560
178561
  const requestBody = error48.options.context?.__requestBody;
178561
178562
  return new ApiError(`Error ${context}: ${message}`, {
178562
- statusCode: error48.response.status,
178563
+ statusCode,
178563
178564
  requestUrl: error48.request.url,
178564
178565
  requestMethod: error48.request.method,
178565
178566
  requestBody,
@@ -178616,6 +178617,12 @@ class ApiError extends SystemError {
178616
178617
  return;
178617
178618
  return REASON_HINTS[reason];
178618
178619
  }
178620
+ static normalizeStatusCode(statusCode, responseBody) {
178621
+ if (responseBody?.error_type === "KeyError") {
178622
+ return 404;
178623
+ }
178624
+ return statusCode;
178625
+ }
178619
178626
  }
178620
178627
 
178621
178628
  class FileNotFoundError extends SystemError {
@@ -185382,18 +185389,16 @@ async function fetchAgents() {
185382
185389
  }
185383
185390
  // src/core/resources/agent/config.ts
185384
185391
  import { join as join3 } from "node:path";
185385
- function toFileSlug(name2) {
185386
- return name2.toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
185387
- }
185392
+ import { isDeepStrictEqual } from "node:util";
185388
185393
  async function readAgentFile(agentPath) {
185389
- const parsed = await readJsonFile(agentPath);
185390
- const result = AgentConfigSchema.safeParse(parsed);
185394
+ const raw2 = await readJsonFile(agentPath);
185395
+ const result = AgentConfigSchema.safeParse(raw2);
185391
185396
  if (!result.success) {
185392
185397
  throw new SchemaValidationError("Invalid agent file", result.error, agentPath);
185393
185398
  }
185394
- return result.data;
185399
+ return { data: result.data, raw: raw2 };
185395
185400
  }
185396
- async function readAllAgents(agentsDir) {
185401
+ async function readAgentFiles(agentsDir) {
185397
185402
  if (!await pathExists(agentsDir)) {
185398
185403
  return [];
185399
185404
  }
@@ -185401,37 +185406,72 @@ async function readAllAgents(agentsDir) {
185401
185406
  cwd: agentsDir,
185402
185407
  absolute: true
185403
185408
  });
185404
- const agents = await Promise.all(files.map((filePath) => readAgentFile(filePath)));
185405
- const names = new Set;
185406
- for (const agent of agents) {
185407
- if (names.has(agent.name)) {
185408
- throw new Error(`Duplicate agent name "${agent.name}"`);
185409
+ return await Promise.all(files.map(async (filePath) => {
185410
+ const { data, raw: raw2 } = await readAgentFile(filePath);
185411
+ return { data, raw: raw2, filePath };
185412
+ }));
185413
+ }
185414
+ function buildNameToEntryMap(entries) {
185415
+ const nameToEntry = new Map;
185416
+ for (const entry of entries) {
185417
+ if (nameToEntry.has(entry.data.name)) {
185418
+ throw new InvalidInputError(`Duplicate agent name "${entry.data.name}"`, {
185419
+ hints: [
185420
+ {
185421
+ message: `Remove duplicate agents with name "${entry.data.name}" - only one agent per name is allowed`
185422
+ }
185423
+ ]
185424
+ });
185425
+ }
185426
+ nameToEntry.set(entry.data.name, entry);
185427
+ }
185428
+ return nameToEntry;
185429
+ }
185430
+ async function readAllAgents(agentsDir) {
185431
+ const entries = await readAgentFiles(agentsDir);
185432
+ const nameToEntry = buildNameToEntryMap(entries);
185433
+ return [...nameToEntry.values()].map((e2) => e2.data);
185434
+ }
185435
+ function findAvailablePath(agentsDir, name2, claimedPaths) {
185436
+ const base = join3(agentsDir, `${name2}.${CONFIG_FILE_EXTENSION}`);
185437
+ if (!claimedPaths.has(base)) {
185438
+ return base;
185439
+ }
185440
+ for (let i = 1;; i++) {
185441
+ const candidate = join3(agentsDir, `${name2}_${i}.${CONFIG_FILE_EXTENSION}`);
185442
+ if (!claimedPaths.has(candidate)) {
185443
+ return candidate;
185409
185444
  }
185410
- names.add(agent.name);
185411
185445
  }
185412
- return agents;
185413
185446
  }
185414
185447
  async function writeAgents(agentsDir, remoteAgents) {
185415
- const existingAgents = await readAllAgents(agentsDir);
185448
+ const entries = await readAgentFiles(agentsDir);
185449
+ const nameToEntry = buildNameToEntryMap(entries);
185416
185450
  const newNames = new Set(remoteAgents.map((a) => a.name));
185417
- const toDelete = existingAgents.filter((a) => !newNames.has(a.name));
185418
- for (const agent of toDelete) {
185419
- const slug = toFileSlug(agent.name);
185420
- const files = await globby(`${slug}.${CONFIG_FILE_EXTENSION_GLOB}`, {
185421
- cwd: agentsDir,
185422
- absolute: true
185423
- });
185424
- for (const filePath of files) {
185425
- await deleteFile(filePath);
185451
+ const deleted = [];
185452
+ for (const [name2, entry] of nameToEntry) {
185453
+ if (!newNames.has(name2)) {
185454
+ await deleteFile(entry.filePath);
185455
+ deleted.push(name2);
185426
185456
  }
185427
185457
  }
185458
+ const claimedPaths = new Set;
185459
+ for (const [name2, entry] of nameToEntry) {
185460
+ if (newNames.has(name2)) {
185461
+ claimedPaths.add(entry.filePath);
185462
+ }
185463
+ }
185464
+ const written = [];
185428
185465
  for (const agent of remoteAgents) {
185429
- const slug = toFileSlug(agent.name);
185430
- const filePath = join3(agentsDir, `${slug}.${CONFIG_FILE_EXTENSION}`);
185466
+ const existing = nameToEntry.get(agent.name);
185467
+ if (existing && isDeepStrictEqual(existing.raw, agent)) {
185468
+ continue;
185469
+ }
185470
+ const filePath = existing?.filePath ?? findAvailablePath(agentsDir, agent.name, claimedPaths);
185471
+ claimedPaths.add(filePath);
185431
185472
  await writeJsonFile(filePath, agent);
185473
+ written.push(agent.name);
185432
185474
  }
185433
- const written = remoteAgents.map((a) => a.name);
185434
- const deleted = toDelete.map((a) => a.name);
185435
185475
  return { written, deleted };
185436
185476
  }
185437
185477
  // src/core/resources/agent/resource.ts
@@ -185648,7 +185688,7 @@ async function removeConnector(integrationType) {
185648
185688
  }
185649
185689
  // src/core/resources/connector/config.ts
185650
185690
  import { join as join4 } from "node:path";
185651
- import { isDeepStrictEqual } from "node:util";
185691
+ import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
185652
185692
  async function readConnectorFile(connectorPath) {
185653
185693
  const parsed = await readJsonFile(connectorPath);
185654
185694
  const result = ConnectorResourceSchema.safeParse(parsed);
@@ -185709,7 +185749,7 @@ async function writeConnectors(connectorsDir, remoteConnectors) {
185709
185749
  type: connector.integrationType,
185710
185750
  scopes: connector.scopes
185711
185751
  };
185712
- if (existing && isDeepStrictEqual(existing.data, localConnector)) {
185752
+ if (existing && isDeepStrictEqual2(existing.data, localConnector)) {
185713
185753
  continue;
185714
185754
  }
185715
185755
  const filePath = existing?.filePath ?? join4(connectorsDir, `${connector.integrationType}.${CONFIG_FILE_EXTENSION}`);
@@ -186012,6 +186052,13 @@ var DeployFunctionsResponseSchema = exports_external.object({
186012
186052
  skipped: exports_external.array(exports_external.string()).optional().nullable(),
186013
186053
  errors: exports_external.array(exports_external.object({ name: exports_external.string(), message: exports_external.string() })).nullable()
186014
186054
  });
186055
+ var LogLevelSchema = exports_external.enum(["info", "warning", "error", "debug"]);
186056
+ var FunctionLogEntrySchema = exports_external.object({
186057
+ time: exports_external.string(),
186058
+ level: LogLevelSchema,
186059
+ message: exports_external.string()
186060
+ });
186061
+ var FunctionLogsResponseSchema = exports_external.array(FunctionLogEntrySchema);
186015
186062
 
186016
186063
  // src/core/resources/function/api.ts
186017
186064
  function toDeployPayloadItem(fn) {
@@ -186042,6 +186089,42 @@ async function deployFunctions(functions) {
186042
186089
  }
186043
186090
  return result.data;
186044
186091
  }
186092
+ function buildLogsQueryString(filters) {
186093
+ const params = new URLSearchParams;
186094
+ if (filters.since) {
186095
+ params.set("since", filters.since);
186096
+ }
186097
+ if (filters.until) {
186098
+ params.set("until", filters.until);
186099
+ }
186100
+ if (filters.level) {
186101
+ params.set("level", filters.level);
186102
+ }
186103
+ if (filters.limit !== undefined) {
186104
+ params.set("limit", String(filters.limit));
186105
+ }
186106
+ if (filters.order) {
186107
+ params.set("order", filters.order);
186108
+ }
186109
+ return params;
186110
+ }
186111
+ async function fetchFunctionLogs(functionName, filters = {}) {
186112
+ const appClient = getAppClient();
186113
+ const searchParams = buildLogsQueryString(filters);
186114
+ let response;
186115
+ try {
186116
+ response = await appClient.get(`functions-mgmt/${functionName}/logs`, {
186117
+ searchParams
186118
+ });
186119
+ } catch (error48) {
186120
+ throw await ApiError.fromHttpError(error48, `fetching function logs: '${functionName}'`);
186121
+ }
186122
+ const result = FunctionLogsResponseSchema.safeParse(await response.json());
186123
+ if (!result.success) {
186124
+ throw new SchemaValidationError("Invalid function logs response from server", result.error);
186125
+ }
186126
+ return result.data;
186127
+ }
186045
186128
  // src/core/resources/function/config.ts
186046
186129
  import { dirname as dirname4, join as join5 } from "node:path";
186047
186130
  async function readFunctionConfig(configPath) {
@@ -193875,7 +193958,7 @@ var {
193875
193958
  // package.json
193876
193959
  var package_default = {
193877
193960
  name: "base44",
193878
- version: "0.0.33",
193961
+ version: "0.0.35",
193879
193962
  description: "Base44 CLI - Unified interface for managing Base44 applications",
193880
193963
  type: "module",
193881
193964
  bin: {
@@ -194003,7 +194086,6 @@ async function printUpgradeNotificationIfAvailable() {
194003
194086
 
194004
194087
  // src/cli/utils/runCommand.ts
194005
194088
  async function runCommand(commandFn, options, context) {
194006
- console.log();
194007
194089
  if (options?.fullBanner) {
194008
194090
  await printBanner(context.isNonInteractive);
194009
194091
  We("");
@@ -194029,8 +194111,11 @@ async function runCommand(commandFn, options, context) {
194029
194111
  const appConfig = await initAppConfig();
194030
194112
  context.errorReporter.setContext({ appId: appConfig.id });
194031
194113
  }
194032
- const { outroMessage } = await commandFn();
194033
- Le(outroMessage || "");
194114
+ const result = await commandFn();
194115
+ Le(result.outroMessage || "");
194116
+ if (result.stdout) {
194117
+ process.stdout.write(result.stdout);
194118
+ }
194034
194119
  } catch (error48) {
194035
194120
  const errorMessage = error48 instanceof Error ? error48.message : String(error48);
194036
194121
  R2.error(errorMessage);
@@ -194078,14 +194163,11 @@ async function pullAgentsAction() {
194078
194163
  successMessage: "Agents fetched successfully",
194079
194164
  errorMessage: "Failed to fetch agents"
194080
194165
  });
194081
- if (remoteAgents.items.length === 0) {
194082
- return { outroMessage: "No agents found on Base44" };
194083
- }
194084
- const { written, deleted } = await runTask("Writing agent files", async () => {
194166
+ const { written, deleted } = await runTask("Syncing agent files", async () => {
194085
194167
  return await writeAgents(agentsDir, remoteAgents.items);
194086
194168
  }, {
194087
- successMessage: "Agent files written successfully",
194088
- errorMessage: "Failed to write agent files"
194169
+ successMessage: "Agent files synced successfully",
194170
+ errorMessage: "Failed to sync agent files"
194089
194171
  });
194090
194172
  if (written.length > 0) {
194091
194173
  R2.success(`Written: ${written.join(", ")}`);
@@ -194093,6 +194175,9 @@ async function pullAgentsAction() {
194093
194175
  if (deleted.length > 0) {
194094
194176
  R2.warn(`Deleted: ${deleted.join(", ")}`);
194095
194177
  }
194178
+ if (written.length === 0 && deleted.length === 0) {
194179
+ R2.info("All agents are already up to date");
194180
+ }
194096
194181
  return {
194097
194182
  outroMessage: `Pulled ${remoteAgents.total} agents to ${agentsDir}`
194098
194183
  };
@@ -195451,6 +195536,125 @@ function getLinkCommand(context) {
195451
195536
  });
195452
195537
  }
195453
195538
 
195539
+ // src/cli/commands/project/logs.ts
195540
+ function parseFunctionFilters(options) {
195541
+ const filters = {};
195542
+ if (options.since) {
195543
+ filters.since = options.since;
195544
+ }
195545
+ if (options.until) {
195546
+ filters.until = options.until;
195547
+ }
195548
+ if (options.level) {
195549
+ filters.level = options.level;
195550
+ }
195551
+ if (options.limit) {
195552
+ filters.limit = Number.parseInt(options.limit, 10);
195553
+ }
195554
+ if (options.order) {
195555
+ filters.order = options.order.toLowerCase();
195556
+ }
195557
+ return filters;
195558
+ }
195559
+ function parseFunctionNames(option) {
195560
+ if (!option)
195561
+ return [];
195562
+ return option.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
195563
+ }
195564
+ function normalizeDatetime(value) {
195565
+ if (/Z$|[+-]\d{2}:\d{2}$/.test(value))
195566
+ return value;
195567
+ return `${value}Z`;
195568
+ }
195569
+ function formatEntry(entry) {
195570
+ const time3 = entry.time.substring(0, 19).replace("T", " ");
195571
+ const level = entry.level.toUpperCase().padEnd(5);
195572
+ const message = entry.message.trim();
195573
+ return `${time3} ${level} ${message}`;
195574
+ }
195575
+ function formatLogs(entries) {
195576
+ if (entries.length === 0) {
195577
+ return `No logs found matching the filters.
195578
+ `;
195579
+ }
195580
+ const header2 = `Showing ${entries.length} function log entries
195581
+ `;
195582
+ return [header2, ...entries.map(formatEntry)].join(`
195583
+ `);
195584
+ }
195585
+ function normalizeLogEntry(entry, functionName) {
195586
+ return {
195587
+ time: entry.time,
195588
+ level: entry.level,
195589
+ message: `[${functionName}] ${entry.message}`,
195590
+ source: functionName
195591
+ };
195592
+ }
195593
+ async function fetchLogsForFunctions(functionNames, options, availableFunctionNames) {
195594
+ const filters = parseFunctionFilters(options);
195595
+ const allEntries = [];
195596
+ for (const functionName of functionNames) {
195597
+ let logs;
195598
+ try {
195599
+ logs = await fetchFunctionLogs(functionName, filters);
195600
+ } catch (error48) {
195601
+ if (error48 instanceof ApiError && error48.statusCode === 404 && availableFunctionNames.length > 0) {
195602
+ const available = availableFunctionNames.join(", ");
195603
+ throw new InvalidInputError(`Function "${functionName}" was not found in this app`, {
195604
+ hints: [
195605
+ {
195606
+ message: `Available functions in this project: ${available}`
195607
+ },
195608
+ {
195609
+ message: "Make sure the function has been deployed before fetching logs",
195610
+ command: "base44 functions deploy"
195611
+ }
195612
+ ]
195613
+ });
195614
+ }
195615
+ throw error48;
195616
+ }
195617
+ const entries = logs.map((entry) => normalizeLogEntry(entry, functionName));
195618
+ allEntries.push(...entries);
195619
+ }
195620
+ if (functionNames.length > 1) {
195621
+ const order = options.order?.toUpperCase() === "ASC" ? 1 : -1;
195622
+ allEntries.sort((a2, b) => order * a2.time.localeCompare(b.time));
195623
+ }
195624
+ return allEntries;
195625
+ }
195626
+ async function getAllFunctionNames() {
195627
+ const { functions } = await readProjectConfig();
195628
+ return functions.map((fn) => fn.name);
195629
+ }
195630
+ async function logsAction(options) {
195631
+ const specifiedFunctions = parseFunctionNames(options.function);
195632
+ const allProjectFunctions = await getAllFunctionNames();
195633
+ const functionNames = specifiedFunctions.length > 0 ? specifiedFunctions : allProjectFunctions;
195634
+ if (functionNames.length === 0) {
195635
+ return { outroMessage: "No functions found in this project." };
195636
+ }
195637
+ let entries = await fetchLogsForFunctions(functionNames, options, allProjectFunctions);
195638
+ const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
195639
+ if (limit !== undefined && entries.length > limit) {
195640
+ entries = entries.slice(0, limit);
195641
+ }
195642
+ const logsOutput = options.json ? `${JSON.stringify(entries, null, 2)}
195643
+ ` : formatLogs(entries);
195644
+ return { outroMessage: "Fetched logs", stdout: logsOutput };
195645
+ }
195646
+ function getLogsCommand(context) {
195647
+ return new Command("logs").description("Fetch function logs for this app").option("--function <names>", "Filter by function name(s), comma-separated. If omitted, fetches logs for all project functions").option("--since <datetime>", "Show logs from this time (ISO format)", normalizeDatetime).option("--until <datetime>", "Show logs until this time (ISO format)", normalizeDatetime).addOption(new Option("--level <level>", "Filter by log level").choices([...LogLevelSchema.options]).hideHelp()).option("-n, --limit <n>", "Results per page (1-1000, default: 50)", (v) => {
195648
+ const n2 = Number.parseInt(v, 10);
195649
+ if (Number.isNaN(n2) || n2 < 1 || n2 > 1000) {
195650
+ throw new InvalidInputError(`Invalid limit: "${v}". Must be a number between 1 and 1000.`);
195651
+ }
195652
+ return v;
195653
+ }).addOption(new Option("--order <order>", "Sort order").choices(["asc", "desc"])).action(async (options) => {
195654
+ await runCommand(() => logsAction(options), { requireAuth: true }, context);
195655
+ });
195656
+ }
195657
+
195454
195658
  // src/cli/commands/site/deploy.ts
195455
195659
  import { resolve as resolve3 } from "node:path";
195456
195660
  async function deployAction2(options) {
@@ -196172,6 +196376,7 @@ function createProgram(context) {
196172
196376
  program2.addCommand(getSiteCommand(context));
196173
196377
  program2.addCommand(getTypesCommand(context));
196174
196378
  program2.addCommand(getDevCommand(context), { hidden: true });
196379
+ program2.addCommand(getLogsCommand(context), { hidden: true });
196175
196380
  return program2;
196176
196381
  }
196177
196382
 
@@ -200436,6 +200641,6 @@ export {
200436
200641
  CLIExitError
200437
200642
  };
200438
200643
 
200439
- //# debugId=DF6807EB90E6667564756E2164756E21
200644
+ //# debugId=97F60A57F6E2DA7C64756E2164756E21
200440
200645
 
200441
- //# chunkId=019c751d-ed06-7271-9f3f-d37c42112446
200646
+ //# chunkId=019c8b01-a41e-78d0-855b-1f264ec2d7de