@base44-preview/cli 0.1.11-pr.602.81713bc → 0.1.12-pr.595.db709c9
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 +216 -7
- package/dist/cli/index.js.map +5 -4
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -247752,6 +247752,137 @@ var functionResource = {
|
|
|
247752
247752
|
readAll: readAllFunctions,
|
|
247753
247753
|
push: (functions) => deployFunctionsSequentially(functions)
|
|
247754
247754
|
};
|
|
247755
|
+
// src/core/resources/function/stream-api.ts
|
|
247756
|
+
var StreamLogEventSchema = exports_external.object({
|
|
247757
|
+
time: exports_external.string(),
|
|
247758
|
+
level: exports_external.preprocess((value) => value === "warn" ? "warning" : value, LogLevelSchema),
|
|
247759
|
+
function: exports_external.string().nullable(),
|
|
247760
|
+
message: exports_external.string()
|
|
247761
|
+
});
|
|
247762
|
+
var StreamEndEventSchema = exports_external.object({
|
|
247763
|
+
reason: exports_external.string(),
|
|
247764
|
+
retriable: exports_external.boolean()
|
|
247765
|
+
});
|
|
247766
|
+
function buildStreamUrl(filters) {
|
|
247767
|
+
const { id } = getAppContext();
|
|
247768
|
+
const url2 = new URL(`/api/apps/${id}/functions-mgmt/logs/stream`, getBase44ApiUrl());
|
|
247769
|
+
if (filters.functions?.length) {
|
|
247770
|
+
url2.searchParams.set("function", filters.functions.join(","));
|
|
247771
|
+
}
|
|
247772
|
+
if (filters.env) {
|
|
247773
|
+
url2.searchParams.set("env", filters.env);
|
|
247774
|
+
}
|
|
247775
|
+
return url2.href;
|
|
247776
|
+
}
|
|
247777
|
+
async function buildStreamAuthHeaders() {
|
|
247778
|
+
const workspaceApiKey = getWorkspaceApiKeyFromEnv();
|
|
247779
|
+
if (workspaceApiKey && isWorkspaceApiKey(workspaceApiKey)) {
|
|
247780
|
+
return { api_key: workspaceApiKey };
|
|
247781
|
+
}
|
|
247782
|
+
const auth = await readAuth();
|
|
247783
|
+
if (isTokenExpired(auth)) {
|
|
247784
|
+
const refreshedToken = await refreshAndSaveTokens();
|
|
247785
|
+
if (refreshedToken) {
|
|
247786
|
+
return { Authorization: `Bearer ${refreshedToken}` };
|
|
247787
|
+
}
|
|
247788
|
+
}
|
|
247789
|
+
return { Authorization: `Bearer ${auth.accessToken}` };
|
|
247790
|
+
}
|
|
247791
|
+
function parseStreamEvent(eventName, data) {
|
|
247792
|
+
try {
|
|
247793
|
+
const payload = JSON.parse(data);
|
|
247794
|
+
if (eventName === "end") {
|
|
247795
|
+
const result = StreamEndEventSchema.safeParse(payload);
|
|
247796
|
+
return result.success ? { kind: "end", end: result.data } : null;
|
|
247797
|
+
}
|
|
247798
|
+
if (eventName === "") {
|
|
247799
|
+
const result = StreamLogEventSchema.safeParse(payload);
|
|
247800
|
+
return result.success ? { kind: "log", log: result.data } : null;
|
|
247801
|
+
}
|
|
247802
|
+
return null;
|
|
247803
|
+
} catch {
|
|
247804
|
+
return null;
|
|
247805
|
+
}
|
|
247806
|
+
}
|
|
247807
|
+
var STREAM_SILENCE_TIMEOUT_MS = 60000;
|
|
247808
|
+
async function readOrSilence(reader) {
|
|
247809
|
+
let timer;
|
|
247810
|
+
const silence = new Promise((resolve3) => {
|
|
247811
|
+
timer = setTimeout(() => resolve3("silence"), STREAM_SILENCE_TIMEOUT_MS);
|
|
247812
|
+
});
|
|
247813
|
+
try {
|
|
247814
|
+
return await Promise.race([reader.read(), silence]);
|
|
247815
|
+
} finally {
|
|
247816
|
+
clearTimeout(timer);
|
|
247817
|
+
}
|
|
247818
|
+
}
|
|
247819
|
+
async function* readLines(body) {
|
|
247820
|
+
const reader = body.getReader();
|
|
247821
|
+
const decoder = new TextDecoder;
|
|
247822
|
+
let buffered = "";
|
|
247823
|
+
try {
|
|
247824
|
+
while (true) {
|
|
247825
|
+
const result = await readOrSilence(reader);
|
|
247826
|
+
if (result === "silence") {
|
|
247827
|
+
await reader.cancel();
|
|
247828
|
+
return;
|
|
247829
|
+
}
|
|
247830
|
+
if (result.done || !result.value)
|
|
247831
|
+
return;
|
|
247832
|
+
buffered += decoder.decode(result.value, { stream: true });
|
|
247833
|
+
const lines = buffered.split(`
|
|
247834
|
+
`);
|
|
247835
|
+
buffered = lines.pop() ?? "";
|
|
247836
|
+
yield* lines;
|
|
247837
|
+
}
|
|
247838
|
+
} finally {
|
|
247839
|
+
reader.releaseLock();
|
|
247840
|
+
}
|
|
247841
|
+
}
|
|
247842
|
+
async function* readStreamEvents(body) {
|
|
247843
|
+
let eventName = "";
|
|
247844
|
+
for await (const line of readLines(body)) {
|
|
247845
|
+
if (line.startsWith("event:")) {
|
|
247846
|
+
eventName = line.slice(6).trim();
|
|
247847
|
+
continue;
|
|
247848
|
+
}
|
|
247849
|
+
if (line.startsWith("data:")) {
|
|
247850
|
+
const event = parseStreamEvent(eventName, line.slice(5));
|
|
247851
|
+
eventName = "";
|
|
247852
|
+
if (event)
|
|
247853
|
+
yield event;
|
|
247854
|
+
continue;
|
|
247855
|
+
}
|
|
247856
|
+
if (line.trim() === "")
|
|
247857
|
+
eventName = "";
|
|
247858
|
+
}
|
|
247859
|
+
}
|
|
247860
|
+
var STREAM_CONNECT_TIMEOUT_MS = 1e4;
|
|
247861
|
+
var isWorthReconnecting = (status) => status >= 500;
|
|
247862
|
+
async function openLogStream(filters) {
|
|
247863
|
+
const connectPhase = new AbortController;
|
|
247864
|
+
const connectTimer = setTimeout(() => connectPhase.abort(), STREAM_CONNECT_TIMEOUT_MS);
|
|
247865
|
+
let response;
|
|
247866
|
+
try {
|
|
247867
|
+
response = await fetch(buildStreamUrl(filters), {
|
|
247868
|
+
headers: {
|
|
247869
|
+
Accept: "text/event-stream",
|
|
247870
|
+
...await buildStreamAuthHeaders()
|
|
247871
|
+
},
|
|
247872
|
+
signal: connectPhase.signal
|
|
247873
|
+
});
|
|
247874
|
+
} catch {
|
|
247875
|
+
return { kind: "transient" };
|
|
247876
|
+
} finally {
|
|
247877
|
+
clearTimeout(connectTimer);
|
|
247878
|
+
}
|
|
247879
|
+
if (!response.ok) {
|
|
247880
|
+
return isWorthReconnecting(response.status) ? { kind: "transient" } : { kind: "refused" };
|
|
247881
|
+
}
|
|
247882
|
+
if (!response.body)
|
|
247883
|
+
return { kind: "transient" };
|
|
247884
|
+
return { kind: "stream", events: readStreamEvents(response.body) };
|
|
247885
|
+
}
|
|
247755
247886
|
// src/core/project/config.ts
|
|
247756
247887
|
class ProjectConfigReader {
|
|
247757
247888
|
pluginSourceByNamespace = new Map;
|
|
@@ -247927,7 +248058,7 @@ import { join as join12 } from "node:path";
|
|
|
247927
248058
|
// package.json
|
|
247928
248059
|
var package_default = {
|
|
247929
248060
|
name: "base44",
|
|
247930
|
-
version: "0.1.
|
|
248061
|
+
version: "0.1.12",
|
|
247931
248062
|
description: "Base44 CLI - Unified interface for managing Base44 applications",
|
|
247932
248063
|
type: "module",
|
|
247933
248064
|
bin: {
|
|
@@ -258338,9 +258469,84 @@ function writeFollowLine(entry, jsonMode) {
|
|
|
258338
258469
|
process.stdout.write(`${line}
|
|
258339
258470
|
`);
|
|
258340
258471
|
}
|
|
258341
|
-
|
|
258342
|
-
|
|
258343
|
-
|
|
258472
|
+
var delay2 = (ms2) => new Promise((resolve9) => setTimeout(resolve9, ms2));
|
|
258473
|
+
function streamEventToLogEntry(event) {
|
|
258474
|
+
return {
|
|
258475
|
+
time: event.time,
|
|
258476
|
+
level: event.level,
|
|
258477
|
+
message: event.function ? `[${event.function}] ${event.message}` : event.message,
|
|
258478
|
+
source: event.function ?? ""
|
|
258479
|
+
};
|
|
258480
|
+
}
|
|
258481
|
+
async function printStreamUntilEnd(stream, levelFilter, jsonMode, startTime) {
|
|
258482
|
+
let lastTime = startTime;
|
|
258483
|
+
let producedEvents = false;
|
|
258484
|
+
try {
|
|
258485
|
+
for await (const event of stream) {
|
|
258486
|
+
producedEvents = true;
|
|
258487
|
+
if (event.kind === "end")
|
|
258488
|
+
return { lastTime, producedEvents, end: event.end };
|
|
258489
|
+
if (levelFilter && event.log.level !== levelFilter)
|
|
258490
|
+
continue;
|
|
258491
|
+
writeFollowLine(streamEventToLogEntry(event.log), jsonMode);
|
|
258492
|
+
if (event.log.time > lastTime)
|
|
258493
|
+
lastTime = event.log.time;
|
|
258494
|
+
}
|
|
258495
|
+
} catch {}
|
|
258496
|
+
return { lastTime, producedEvents, end: null };
|
|
258497
|
+
}
|
|
258498
|
+
var STREAM_RECONNECT_DELAY_MS = 1000;
|
|
258499
|
+
var MAX_DROPS_SINCE_LAST_EVENT = 2;
|
|
258500
|
+
var CONNECT_RETRY_DELAYS_MS = [1000, 2000, 4000, 8000];
|
|
258501
|
+
async function connectWhileTransientlyUnavailable(filters) {
|
|
258502
|
+
let attempt = await openLogStream(filters);
|
|
258503
|
+
for (const retryDelay of CONNECT_RETRY_DELAYS_MS) {
|
|
258504
|
+
if (attempt.kind !== "transient")
|
|
258505
|
+
return attempt;
|
|
258506
|
+
await delay2(retryDelay);
|
|
258507
|
+
attempt = await openLogStream(filters);
|
|
258508
|
+
}
|
|
258509
|
+
return attempt;
|
|
258510
|
+
}
|
|
258511
|
+
async function streamUntilExhausted(options, jsonMode) {
|
|
258512
|
+
const filters = {
|
|
258513
|
+
functions: parseFunctionNames(options.function),
|
|
258514
|
+
env: options.env
|
|
258515
|
+
};
|
|
258516
|
+
let everConnected = false;
|
|
258517
|
+
let lastTime = "";
|
|
258518
|
+
let dropsSinceLastEvent = 0;
|
|
258519
|
+
while (true) {
|
|
258520
|
+
const attempt = await connectWhileTransientlyUnavailable(filters);
|
|
258521
|
+
if (attempt.kind !== "stream")
|
|
258522
|
+
break;
|
|
258523
|
+
everConnected = true;
|
|
258524
|
+
const ending = await printStreamUntilEnd(attempt.events, options.level, jsonMode, lastTime);
|
|
258525
|
+
lastTime = ending.lastTime;
|
|
258526
|
+
if (ending.end) {
|
|
258527
|
+
if (!ending.end.retriable)
|
|
258528
|
+
break;
|
|
258529
|
+
dropsSinceLastEvent = 0;
|
|
258530
|
+
} else {
|
|
258531
|
+
dropsSinceLastEvent = ending.producedEvents ? 1 : dropsSinceLastEvent + 1;
|
|
258532
|
+
if (dropsSinceLastEvent >= MAX_DROPS_SINCE_LAST_EVENT)
|
|
258533
|
+
break;
|
|
258534
|
+
}
|
|
258535
|
+
await delay2(STREAM_RECONNECT_DELAY_MS);
|
|
258536
|
+
}
|
|
258537
|
+
return { everConnected, lastTime };
|
|
258538
|
+
}
|
|
258539
|
+
async function followLogs(functionNames, options, availableFunctionNames, jsonMode, logger2) {
|
|
258540
|
+
const { everConnected, lastTime } = await streamUntilExhausted(options, jsonMode);
|
|
258541
|
+
logger2.warn(everConnected ? "Realtime stream disconnected — falling back to polling (lines may lag ~20-30s)." : "Realtime stream unavailable — falling back to polling (lines may lag ~20-30s).");
|
|
258542
|
+
return pollLogs(functionNames, options, availableFunctionNames, jsonMode, {
|
|
258543
|
+
lastTime,
|
|
258544
|
+
boundaryKeys: new Set
|
|
258545
|
+
});
|
|
258546
|
+
}
|
|
258547
|
+
async function pollLogs(functionNames, options, availableFunctionNames, jsonMode, initialState) {
|
|
258548
|
+
let state = initialState;
|
|
258549
|
+
let first = state.lastTime === "";
|
|
258344
258550
|
while (true) {
|
|
258345
258551
|
const pollOptions = first ? options : { ...options, since: state.lastTime };
|
|
258346
258552
|
const entries = await fetchLogsForFunctions(functionNames, pollOptions, availableFunctionNames);
|
|
@@ -258350,7 +258556,7 @@ async function followLogs(functionNames, options, availableFunctionNames, jsonMo
|
|
|
258350
258556
|
for (const entry of fresh)
|
|
258351
258557
|
writeFollowLine(entry, jsonMode);
|
|
258352
258558
|
first = false;
|
|
258353
|
-
await
|
|
258559
|
+
await delay2(2000);
|
|
258354
258560
|
}
|
|
258355
258561
|
}
|
|
258356
258562
|
function formatLogs(entries, env3) {
|
|
@@ -258442,6 +258648,9 @@ async function logsAction(ctx, options) {
|
|
|
258442
258648
|
return { outroMessage: "No functions found in this app." };
|
|
258443
258649
|
}
|
|
258444
258650
|
if (options.follow) {
|
|
258651
|
+
if (options.since) {
|
|
258652
|
+
throw new InvalidInputError("--since cannot be combined with --follow yet (the realtime stream starts from now).");
|
|
258653
|
+
}
|
|
258445
258654
|
if (options.until) {
|
|
258446
258655
|
throw new InvalidInputError("--until cannot be combined with --follow (a stream has no end).");
|
|
258447
258656
|
}
|
|
@@ -258449,7 +258658,7 @@ async function logsAction(ctx, options) {
|
|
|
258449
258658
|
throw new InvalidInputError("--order cannot be combined with --follow (a live tail always streams oldest to newest).");
|
|
258450
258659
|
}
|
|
258451
258660
|
options.order = "asc";
|
|
258452
|
-
return followLogs(functionNames, options, availableFunctionNames, ctx.jsonMode);
|
|
258661
|
+
return followLogs(functionNames, options, availableFunctionNames, ctx.jsonMode, ctx.log);
|
|
258453
258662
|
}
|
|
258454
258663
|
let entries = await fetchLogsForFunctions(functionNames, options, availableFunctionNames);
|
|
258455
258664
|
const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
|
|
@@ -268098,4 +268307,4 @@ export {
|
|
|
268098
268307
|
runCLI
|
|
268099
268308
|
};
|
|
268100
268309
|
|
|
268101
|
-
//# debugId=
|
|
268310
|
+
//# debugId=9A9871757366EC3764756E2164756E21
|