@base44-preview/cli 0.0.33-pr.286.941c114 → 0.0.34-pr.228.2ae7cac
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 +220 -41
- package/dist/cli/index.js.map +11 -10
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
185390
|
-
const result = AgentConfigSchema.safeParse(
|
|
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
|
|
185401
|
+
async function readAgentFiles(agentsDir) {
|
|
185397
185402
|
if (!await pathExists(agentsDir)) {
|
|
185398
185403
|
return [];
|
|
185399
185404
|
}
|
|
@@ -185401,37 +185406,49 @@ async function readAllAgents(agentsDir) {
|
|
|
185401
185406
|
cwd: agentsDir,
|
|
185402
185407
|
absolute: true
|
|
185403
185408
|
});
|
|
185404
|
-
|
|
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
|
+
async function readAllAgents(agentsDir) {
|
|
185415
|
+
const entries = await readAgentFiles(agentsDir);
|
|
185405
185416
|
const names = new Set;
|
|
185406
|
-
for (const
|
|
185407
|
-
if (names.has(
|
|
185408
|
-
throw new Error(`Duplicate agent name "${
|
|
185417
|
+
for (const { data } of entries) {
|
|
185418
|
+
if (names.has(data.name)) {
|
|
185419
|
+
throw new Error(`Duplicate agent name "${data.name}"`);
|
|
185409
185420
|
}
|
|
185410
|
-
names.add(
|
|
185421
|
+
names.add(data.name);
|
|
185411
185422
|
}
|
|
185412
|
-
return
|
|
185423
|
+
return entries.map((e2) => e2.data);
|
|
185413
185424
|
}
|
|
185414
185425
|
async function writeAgents(agentsDir, remoteAgents) {
|
|
185415
|
-
const
|
|
185426
|
+
const entries = await readAgentFiles(agentsDir);
|
|
185427
|
+
const nameToEntry = new Map;
|
|
185428
|
+
for (const entry of entries) {
|
|
185429
|
+
if (nameToEntry.has(entry.data.name)) {
|
|
185430
|
+
throw new Error(`Duplicate agent name "${entry.data.name}"`);
|
|
185431
|
+
}
|
|
185432
|
+
nameToEntry.set(entry.data.name, entry);
|
|
185433
|
+
}
|
|
185416
185434
|
const newNames = new Set(remoteAgents.map((a) => a.name));
|
|
185417
|
-
const
|
|
185418
|
-
for (const
|
|
185419
|
-
|
|
185420
|
-
|
|
185421
|
-
|
|
185422
|
-
absolute: true
|
|
185423
|
-
});
|
|
185424
|
-
for (const filePath of files) {
|
|
185425
|
-
await deleteFile(filePath);
|
|
185435
|
+
const deleted = [];
|
|
185436
|
+
for (const [name2, entry] of nameToEntry) {
|
|
185437
|
+
if (!newNames.has(name2)) {
|
|
185438
|
+
await deleteFile(entry.filePath);
|
|
185439
|
+
deleted.push(name2);
|
|
185426
185440
|
}
|
|
185427
185441
|
}
|
|
185442
|
+
const written = [];
|
|
185428
185443
|
for (const agent of remoteAgents) {
|
|
185429
|
-
const
|
|
185430
|
-
|
|
185444
|
+
const existing = nameToEntry.get(agent.name);
|
|
185445
|
+
if (existing && isDeepStrictEqual(existing.raw, agent)) {
|
|
185446
|
+
continue;
|
|
185447
|
+
}
|
|
185448
|
+
const filePath = existing?.filePath ?? join3(agentsDir, `${agent.name}.${CONFIG_FILE_EXTENSION}`);
|
|
185431
185449
|
await writeJsonFile(filePath, agent);
|
|
185450
|
+
written.push(agent.name);
|
|
185432
185451
|
}
|
|
185433
|
-
const written = remoteAgents.map((a) => a.name);
|
|
185434
|
-
const deleted = toDelete.map((a) => a.name);
|
|
185435
185452
|
return { written, deleted };
|
|
185436
185453
|
}
|
|
185437
185454
|
// src/core/resources/agent/resource.ts
|
|
@@ -185648,7 +185665,7 @@ async function removeConnector(integrationType) {
|
|
|
185648
185665
|
}
|
|
185649
185666
|
// src/core/resources/connector/config.ts
|
|
185650
185667
|
import { join as join4 } from "node:path";
|
|
185651
|
-
import { isDeepStrictEqual } from "node:util";
|
|
185668
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
185652
185669
|
async function readConnectorFile(connectorPath) {
|
|
185653
185670
|
const parsed = await readJsonFile(connectorPath);
|
|
185654
185671
|
const result = ConnectorResourceSchema.safeParse(parsed);
|
|
@@ -185709,7 +185726,7 @@ async function writeConnectors(connectorsDir, remoteConnectors) {
|
|
|
185709
185726
|
type: connector.integrationType,
|
|
185710
185727
|
scopes: connector.scopes
|
|
185711
185728
|
};
|
|
185712
|
-
if (existing &&
|
|
185729
|
+
if (existing && isDeepStrictEqual2(existing.data, localConnector)) {
|
|
185713
185730
|
continue;
|
|
185714
185731
|
}
|
|
185715
185732
|
const filePath = existing?.filePath ?? join4(connectorsDir, `${connector.integrationType}.${CONFIG_FILE_EXTENSION}`);
|
|
@@ -186012,6 +186029,13 @@ var DeployFunctionsResponseSchema = exports_external.object({
|
|
|
186012
186029
|
skipped: exports_external.array(exports_external.string()).optional().nullable(),
|
|
186013
186030
|
errors: exports_external.array(exports_external.object({ name: exports_external.string(), message: exports_external.string() })).nullable()
|
|
186014
186031
|
});
|
|
186032
|
+
var LogLevelSchema = exports_external.enum(["log", "info", "warn", "error", "debug"]);
|
|
186033
|
+
var FunctionLogEntrySchema = exports_external.object({
|
|
186034
|
+
time: exports_external.string(),
|
|
186035
|
+
level: LogLevelSchema,
|
|
186036
|
+
message: exports_external.string()
|
|
186037
|
+
});
|
|
186038
|
+
var FunctionLogsResponseSchema = exports_external.array(FunctionLogEntrySchema);
|
|
186015
186039
|
|
|
186016
186040
|
// src/core/resources/function/api.ts
|
|
186017
186041
|
function toDeployPayloadItem(fn) {
|
|
@@ -186042,6 +186066,42 @@ async function deployFunctions(functions) {
|
|
|
186042
186066
|
}
|
|
186043
186067
|
return result.data;
|
|
186044
186068
|
}
|
|
186069
|
+
function buildLogsQueryString(filters) {
|
|
186070
|
+
const params = new URLSearchParams;
|
|
186071
|
+
if (filters.since) {
|
|
186072
|
+
params.set("since", filters.since);
|
|
186073
|
+
}
|
|
186074
|
+
if (filters.until) {
|
|
186075
|
+
params.set("until", filters.until);
|
|
186076
|
+
}
|
|
186077
|
+
if (filters.level) {
|
|
186078
|
+
params.set("level", filters.level);
|
|
186079
|
+
}
|
|
186080
|
+
if (filters.limit !== undefined) {
|
|
186081
|
+
params.set("limit", String(filters.limit));
|
|
186082
|
+
}
|
|
186083
|
+
if (filters.order) {
|
|
186084
|
+
params.set("order", filters.order);
|
|
186085
|
+
}
|
|
186086
|
+
return params;
|
|
186087
|
+
}
|
|
186088
|
+
async function fetchFunctionLogs(functionName, filters = {}) {
|
|
186089
|
+
const appClient = getAppClient();
|
|
186090
|
+
const searchParams = buildLogsQueryString(filters);
|
|
186091
|
+
let response;
|
|
186092
|
+
try {
|
|
186093
|
+
response = await appClient.get(`functions-mgmt/${functionName}/logs`, {
|
|
186094
|
+
searchParams
|
|
186095
|
+
});
|
|
186096
|
+
} catch (error48) {
|
|
186097
|
+
throw await ApiError.fromHttpError(error48, `fetching function logs: '${functionName}'`);
|
|
186098
|
+
}
|
|
186099
|
+
const result = FunctionLogsResponseSchema.safeParse(await response.json());
|
|
186100
|
+
if (!result.success) {
|
|
186101
|
+
throw new SchemaValidationError("Invalid function logs response from server", result.error);
|
|
186102
|
+
}
|
|
186103
|
+
return result.data;
|
|
186104
|
+
}
|
|
186045
186105
|
// src/core/resources/function/config.ts
|
|
186046
186106
|
import { dirname as dirname4, join as join5 } from "node:path";
|
|
186047
186107
|
async function readFunctionConfig(configPath) {
|
|
@@ -193875,7 +193935,7 @@ var {
|
|
|
193875
193935
|
// package.json
|
|
193876
193936
|
var package_default = {
|
|
193877
193937
|
name: "base44",
|
|
193878
|
-
version: "0.0.
|
|
193938
|
+
version: "0.0.34",
|
|
193879
193939
|
description: "Base44 CLI - Unified interface for managing Base44 applications",
|
|
193880
193940
|
type: "module",
|
|
193881
193941
|
bin: {
|
|
@@ -194003,7 +194063,6 @@ async function printUpgradeNotificationIfAvailable() {
|
|
|
194003
194063
|
|
|
194004
194064
|
// src/cli/utils/runCommand.ts
|
|
194005
194065
|
async function runCommand(commandFn, options, context) {
|
|
194006
|
-
console.log();
|
|
194007
194066
|
if (options?.fullBanner) {
|
|
194008
194067
|
await printBanner(context.isNonInteractive);
|
|
194009
194068
|
We("");
|
|
@@ -194029,8 +194088,11 @@ async function runCommand(commandFn, options, context) {
|
|
|
194029
194088
|
const appConfig = await initAppConfig();
|
|
194030
194089
|
context.errorReporter.setContext({ appId: appConfig.id });
|
|
194031
194090
|
}
|
|
194032
|
-
const
|
|
194033
|
-
Le(outroMessage || "");
|
|
194091
|
+
const result = await commandFn();
|
|
194092
|
+
Le(result.outroMessage || "");
|
|
194093
|
+
if (result.stdout) {
|
|
194094
|
+
process.stdout.write(result.stdout);
|
|
194095
|
+
}
|
|
194034
194096
|
} catch (error48) {
|
|
194035
194097
|
const errorMessage = error48 instanceof Error ? error48.message : String(error48);
|
|
194036
194098
|
R2.error(errorMessage);
|
|
@@ -194078,14 +194140,11 @@ async function pullAgentsAction() {
|
|
|
194078
194140
|
successMessage: "Agents fetched successfully",
|
|
194079
194141
|
errorMessage: "Failed to fetch agents"
|
|
194080
194142
|
});
|
|
194081
|
-
|
|
194082
|
-
return { outroMessage: "No agents found on Base44" };
|
|
194083
|
-
}
|
|
194084
|
-
const { written, deleted } = await runTask("Writing agent files", async () => {
|
|
194143
|
+
const { written, deleted } = await runTask("Syncing agent files", async () => {
|
|
194085
194144
|
return await writeAgents(agentsDir, remoteAgents.items);
|
|
194086
194145
|
}, {
|
|
194087
|
-
successMessage: "Agent files
|
|
194088
|
-
errorMessage: "Failed to
|
|
194146
|
+
successMessage: "Agent files synced successfully",
|
|
194147
|
+
errorMessage: "Failed to sync agent files"
|
|
194089
194148
|
});
|
|
194090
194149
|
if (written.length > 0) {
|
|
194091
194150
|
R2.success(`Written: ${written.join(", ")}`);
|
|
@@ -194093,6 +194152,9 @@ async function pullAgentsAction() {
|
|
|
194093
194152
|
if (deleted.length > 0) {
|
|
194094
194153
|
R2.warn(`Deleted: ${deleted.join(", ")}`);
|
|
194095
194154
|
}
|
|
194155
|
+
if (written.length === 0 && deleted.length === 0) {
|
|
194156
|
+
R2.info("All agents are already up to date");
|
|
194157
|
+
}
|
|
194096
194158
|
return {
|
|
194097
194159
|
outroMessage: `Pulled ${remoteAgents.total} agents to ${agentsDir}`
|
|
194098
194160
|
};
|
|
@@ -195451,6 +195513,122 @@ function getLinkCommand(context) {
|
|
|
195451
195513
|
});
|
|
195452
195514
|
}
|
|
195453
195515
|
|
|
195516
|
+
// src/cli/commands/project/logs.ts
|
|
195517
|
+
function parseFunctionFilters(options) {
|
|
195518
|
+
const filters = {};
|
|
195519
|
+
if (options.since) {
|
|
195520
|
+
filters.since = options.since;
|
|
195521
|
+
}
|
|
195522
|
+
if (options.until) {
|
|
195523
|
+
filters.until = options.until;
|
|
195524
|
+
}
|
|
195525
|
+
if (options.limit) {
|
|
195526
|
+
filters.limit = Number.parseInt(options.limit, 10);
|
|
195527
|
+
}
|
|
195528
|
+
if (options.order) {
|
|
195529
|
+
filters.order = options.order.toLowerCase();
|
|
195530
|
+
}
|
|
195531
|
+
return filters;
|
|
195532
|
+
}
|
|
195533
|
+
function parseFunctionNames(option) {
|
|
195534
|
+
if (!option)
|
|
195535
|
+
return [];
|
|
195536
|
+
return option.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
195537
|
+
}
|
|
195538
|
+
function normalizeDatetime(value) {
|
|
195539
|
+
if (/Z$|[+-]\d{2}:\d{2}$/.test(value))
|
|
195540
|
+
return value;
|
|
195541
|
+
return `${value}Z`;
|
|
195542
|
+
}
|
|
195543
|
+
function formatEntry(entry) {
|
|
195544
|
+
const time3 = entry.time.substring(0, 19).replace("T", " ");
|
|
195545
|
+
const level = entry.level.toUpperCase().padEnd(5);
|
|
195546
|
+
const message = entry.message.trim();
|
|
195547
|
+
return `${time3} ${level} ${message}`;
|
|
195548
|
+
}
|
|
195549
|
+
function formatLogs(entries) {
|
|
195550
|
+
if (entries.length === 0) {
|
|
195551
|
+
return `No logs found matching the filters.
|
|
195552
|
+
`;
|
|
195553
|
+
}
|
|
195554
|
+
const header2 = `Showing ${entries.length} function log entries
|
|
195555
|
+
`;
|
|
195556
|
+
return [header2, ...entries.map(formatEntry)].join(`
|
|
195557
|
+
`);
|
|
195558
|
+
}
|
|
195559
|
+
function normalizeLogEntry(entry, functionName) {
|
|
195560
|
+
return {
|
|
195561
|
+
time: entry.time,
|
|
195562
|
+
level: entry.level,
|
|
195563
|
+
message: `[${functionName}] ${entry.message}`,
|
|
195564
|
+
source: functionName
|
|
195565
|
+
};
|
|
195566
|
+
}
|
|
195567
|
+
async function fetchLogsForFunctions(functionNames, options, availableFunctionNames) {
|
|
195568
|
+
const filters = parseFunctionFilters(options);
|
|
195569
|
+
const allEntries = [];
|
|
195570
|
+
for (const functionName of functionNames) {
|
|
195571
|
+
let logs;
|
|
195572
|
+
try {
|
|
195573
|
+
logs = await fetchFunctionLogs(functionName, filters);
|
|
195574
|
+
} catch (error48) {
|
|
195575
|
+
if (error48 instanceof ApiError && error48.statusCode === 404 && availableFunctionNames.length > 0) {
|
|
195576
|
+
const available = availableFunctionNames.join(", ");
|
|
195577
|
+
throw new InvalidInputError(`Function "${functionName}" was not found in this app`, {
|
|
195578
|
+
hints: [
|
|
195579
|
+
{
|
|
195580
|
+
message: `Available functions in this project: ${available}`
|
|
195581
|
+
},
|
|
195582
|
+
{
|
|
195583
|
+
message: "Make sure the function has been deployed before fetching logs",
|
|
195584
|
+
command: "base44 functions deploy"
|
|
195585
|
+
}
|
|
195586
|
+
]
|
|
195587
|
+
});
|
|
195588
|
+
}
|
|
195589
|
+
throw error48;
|
|
195590
|
+
}
|
|
195591
|
+
const entries = logs.map((entry) => normalizeLogEntry(entry, functionName));
|
|
195592
|
+
allEntries.push(...entries);
|
|
195593
|
+
}
|
|
195594
|
+
if (functionNames.length > 1) {
|
|
195595
|
+
const order = options.order?.toUpperCase() === "ASC" ? 1 : -1;
|
|
195596
|
+
allEntries.sort((a2, b) => order * a2.time.localeCompare(b.time));
|
|
195597
|
+
}
|
|
195598
|
+
return allEntries;
|
|
195599
|
+
}
|
|
195600
|
+
async function getAllFunctionNames() {
|
|
195601
|
+
const { functions } = await readProjectConfig();
|
|
195602
|
+
return functions.map((fn) => fn.name);
|
|
195603
|
+
}
|
|
195604
|
+
async function logsAction(options) {
|
|
195605
|
+
const specifiedFunctions = parseFunctionNames(options.function);
|
|
195606
|
+
const allProjectFunctions = await getAllFunctionNames();
|
|
195607
|
+
const functionNames = specifiedFunctions.length > 0 ? specifiedFunctions : allProjectFunctions;
|
|
195608
|
+
if (functionNames.length === 0) {
|
|
195609
|
+
return { outroMessage: "No functions found in this project." };
|
|
195610
|
+
}
|
|
195611
|
+
let entries = await fetchLogsForFunctions(functionNames, options, allProjectFunctions);
|
|
195612
|
+
const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
|
|
195613
|
+
if (limit !== undefined && entries.length > limit) {
|
|
195614
|
+
entries = entries.slice(0, limit);
|
|
195615
|
+
}
|
|
195616
|
+
const logsOutput = options.json ? `${JSON.stringify(entries, null, 2)}
|
|
195617
|
+
` : formatLogs(entries);
|
|
195618
|
+
return { outroMessage: "Fetched logs", stdout: logsOutput };
|
|
195619
|
+
}
|
|
195620
|
+
function getLogsCommand(context) {
|
|
195621
|
+
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).option("-n, --limit <n>", "Results per page (1-1000, default: 50)", (v) => {
|
|
195622
|
+
const n2 = Number.parseInt(v, 10);
|
|
195623
|
+
if (Number.isNaN(n2) || n2 < 1 || n2 > 1000) {
|
|
195624
|
+
throw new InvalidInputError(`Invalid limit: "${v}". Must be a number between 1 and 1000.`);
|
|
195625
|
+
}
|
|
195626
|
+
return v;
|
|
195627
|
+
}).addOption(new Option("--order <order>", "Sort order").choices(["asc", "desc"])).option("--json", "Output raw JSON").action(async (options) => {
|
|
195628
|
+
await runCommand(() => logsAction(options), { requireAuth: true }, context);
|
|
195629
|
+
});
|
|
195630
|
+
}
|
|
195631
|
+
|
|
195454
195632
|
// src/cli/commands/site/deploy.ts
|
|
195455
195633
|
import { resolve as resolve3 } from "node:path";
|
|
195456
195634
|
async function deployAction2(options) {
|
|
@@ -196172,6 +196350,7 @@ function createProgram(context) {
|
|
|
196172
196350
|
program2.addCommand(getSiteCommand(context));
|
|
196173
196351
|
program2.addCommand(getTypesCommand(context));
|
|
196174
196352
|
program2.addCommand(getDevCommand(context), { hidden: true });
|
|
196353
|
+
program2.addCommand(getLogsCommand(context), { hidden: true });
|
|
196175
196354
|
return program2;
|
|
196176
196355
|
}
|
|
196177
196356
|
|
|
@@ -200436,4 +200615,4 @@ export {
|
|
|
200436
200615
|
CLIExitError
|
|
200437
200616
|
};
|
|
200438
200617
|
|
|
200439
|
-
//# debugId=
|
|
200618
|
+
//# debugId=199B0E01CD0F366764756E2164756E21
|