@base44-preview/cli 0.1.8-pr.600.002d9ac → 0.1.9-pr.595.21d640d
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 +201 -7
- package/dist/cli/index.js.map +5 -4
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -247872,6 +247872,133 @@ var functionResource = {
|
|
|
247872
247872
|
readAll: readAllFunctions,
|
|
247873
247873
|
push: (functions) => deployFunctionsSequentially(functions)
|
|
247874
247874
|
};
|
|
247875
|
+
// src/core/resources/function/stream-api.ts
|
|
247876
|
+
var StreamLogEventSchema = exports_external.object({
|
|
247877
|
+
time: exports_external.string(),
|
|
247878
|
+
level: exports_external.preprocess((value) => value === "warn" ? "warning" : value, LogLevelSchema),
|
|
247879
|
+
function: exports_external.string().nullable(),
|
|
247880
|
+
message: exports_external.string()
|
|
247881
|
+
});
|
|
247882
|
+
var StreamEndEventSchema = exports_external.object({
|
|
247883
|
+
reason: exports_external.string(),
|
|
247884
|
+
retriable: exports_external.boolean()
|
|
247885
|
+
});
|
|
247886
|
+
function buildStreamUrl(filters) {
|
|
247887
|
+
const { id } = getAppContext();
|
|
247888
|
+
const url2 = new URL(`/api/apps/${id}/functions-mgmt/logs/stream`, getBase44ApiUrl());
|
|
247889
|
+
if (filters.functions?.length) {
|
|
247890
|
+
url2.searchParams.set("function", filters.functions.join(","));
|
|
247891
|
+
}
|
|
247892
|
+
if (filters.env) {
|
|
247893
|
+
url2.searchParams.set("env", filters.env);
|
|
247894
|
+
}
|
|
247895
|
+
return url2.href;
|
|
247896
|
+
}
|
|
247897
|
+
async function buildStreamAuthHeaders() {
|
|
247898
|
+
const workspaceApiKey = getWorkspaceApiKeyFromEnv();
|
|
247899
|
+
if (workspaceApiKey && isWorkspaceApiKey(workspaceApiKey)) {
|
|
247900
|
+
return { api_key: workspaceApiKey };
|
|
247901
|
+
}
|
|
247902
|
+
const auth = await readAuth();
|
|
247903
|
+
if (isTokenExpired(auth)) {
|
|
247904
|
+
const refreshedToken = await refreshAndSaveTokens();
|
|
247905
|
+
if (refreshedToken) {
|
|
247906
|
+
return { Authorization: `Bearer ${refreshedToken}` };
|
|
247907
|
+
}
|
|
247908
|
+
}
|
|
247909
|
+
return { Authorization: `Bearer ${auth.accessToken}` };
|
|
247910
|
+
}
|
|
247911
|
+
function parseStreamEvent(eventName, data) {
|
|
247912
|
+
try {
|
|
247913
|
+
const payload = JSON.parse(data);
|
|
247914
|
+
if (eventName === "end") {
|
|
247915
|
+
const result = StreamEndEventSchema.safeParse(payload);
|
|
247916
|
+
return result.success ? { kind: "end", end: result.data } : null;
|
|
247917
|
+
}
|
|
247918
|
+
if (eventName === "") {
|
|
247919
|
+
const result = StreamLogEventSchema.safeParse(payload);
|
|
247920
|
+
return result.success ? { kind: "log", log: result.data } : null;
|
|
247921
|
+
}
|
|
247922
|
+
return null;
|
|
247923
|
+
} catch {
|
|
247924
|
+
return null;
|
|
247925
|
+
}
|
|
247926
|
+
}
|
|
247927
|
+
var STREAM_SILENCE_TIMEOUT_MS = 60000;
|
|
247928
|
+
async function readOrSilence(reader) {
|
|
247929
|
+
let timer;
|
|
247930
|
+
const silence = new Promise((resolve3) => {
|
|
247931
|
+
timer = setTimeout(() => resolve3("silence"), STREAM_SILENCE_TIMEOUT_MS);
|
|
247932
|
+
});
|
|
247933
|
+
try {
|
|
247934
|
+
return await Promise.race([reader.read(), silence]);
|
|
247935
|
+
} finally {
|
|
247936
|
+
clearTimeout(timer);
|
|
247937
|
+
}
|
|
247938
|
+
}
|
|
247939
|
+
async function* readLines(body) {
|
|
247940
|
+
const reader = body.getReader();
|
|
247941
|
+
const decoder = new TextDecoder;
|
|
247942
|
+
let buffered = "";
|
|
247943
|
+
try {
|
|
247944
|
+
while (true) {
|
|
247945
|
+
const result = await readOrSilence(reader);
|
|
247946
|
+
if (result === "silence") {
|
|
247947
|
+
await reader.cancel();
|
|
247948
|
+
return;
|
|
247949
|
+
}
|
|
247950
|
+
if (result.done || !result.value)
|
|
247951
|
+
return;
|
|
247952
|
+
buffered += decoder.decode(result.value, { stream: true });
|
|
247953
|
+
const lines = buffered.split(`
|
|
247954
|
+
`);
|
|
247955
|
+
buffered = lines.pop() ?? "";
|
|
247956
|
+
yield* lines;
|
|
247957
|
+
}
|
|
247958
|
+
} finally {
|
|
247959
|
+
reader.releaseLock();
|
|
247960
|
+
}
|
|
247961
|
+
}
|
|
247962
|
+
async function* readStreamEvents(body) {
|
|
247963
|
+
let eventName = "";
|
|
247964
|
+
for await (const line of readLines(body)) {
|
|
247965
|
+
if (line.startsWith("event:")) {
|
|
247966
|
+
eventName = line.slice(6).trim();
|
|
247967
|
+
continue;
|
|
247968
|
+
}
|
|
247969
|
+
if (line.startsWith("data:")) {
|
|
247970
|
+
const event = parseStreamEvent(eventName, line.slice(5));
|
|
247971
|
+
eventName = "";
|
|
247972
|
+
if (event)
|
|
247973
|
+
yield event;
|
|
247974
|
+
continue;
|
|
247975
|
+
}
|
|
247976
|
+
if (line.trim() === "")
|
|
247977
|
+
eventName = "";
|
|
247978
|
+
}
|
|
247979
|
+
}
|
|
247980
|
+
var STREAM_CONNECT_TIMEOUT_MS = 1e4;
|
|
247981
|
+
async function openLogStream(filters) {
|
|
247982
|
+
const connectPhase = new AbortController;
|
|
247983
|
+
const connectTimer = setTimeout(() => connectPhase.abort(), STREAM_CONNECT_TIMEOUT_MS);
|
|
247984
|
+
let response;
|
|
247985
|
+
try {
|
|
247986
|
+
response = await fetch(buildStreamUrl(filters), {
|
|
247987
|
+
headers: {
|
|
247988
|
+
Accept: "text/event-stream",
|
|
247989
|
+
...await buildStreamAuthHeaders()
|
|
247990
|
+
},
|
|
247991
|
+
signal: connectPhase.signal
|
|
247992
|
+
});
|
|
247993
|
+
} catch {
|
|
247994
|
+
return null;
|
|
247995
|
+
} finally {
|
|
247996
|
+
clearTimeout(connectTimer);
|
|
247997
|
+
}
|
|
247998
|
+
if (!response.ok || !response.body)
|
|
247999
|
+
return null;
|
|
248000
|
+
return readStreamEvents(response.body);
|
|
248001
|
+
}
|
|
247875
248002
|
// src/core/project/config.ts
|
|
247876
248003
|
class ProjectConfigReader {
|
|
247877
248004
|
pluginSourceByNamespace = new Map;
|
|
@@ -248047,7 +248174,7 @@ import { join as join12 } from "node:path";
|
|
|
248047
248174
|
// package.json
|
|
248048
248175
|
var package_default = {
|
|
248049
248176
|
name: "base44",
|
|
248050
|
-
version: "0.1.
|
|
248177
|
+
version: "0.1.9",
|
|
248051
248178
|
description: "Base44 CLI - Unified interface for managing Base44 applications",
|
|
248052
248179
|
type: "module",
|
|
248053
248180
|
bin: {
|
|
@@ -258454,9 +258581,73 @@ function writeFollowLine(entry, jsonMode) {
|
|
|
258454
258581
|
process.stdout.write(`${line}
|
|
258455
258582
|
`);
|
|
258456
258583
|
}
|
|
258457
|
-
|
|
258458
|
-
|
|
258459
|
-
|
|
258584
|
+
var delay2 = (ms2) => new Promise((resolve9) => setTimeout(resolve9, ms2));
|
|
258585
|
+
function streamEventToLogEntry(event) {
|
|
258586
|
+
return {
|
|
258587
|
+
time: event.time,
|
|
258588
|
+
level: event.level,
|
|
258589
|
+
message: event.function ? `[${event.function}] ${event.message}` : event.message,
|
|
258590
|
+
source: event.function ?? ""
|
|
258591
|
+
};
|
|
258592
|
+
}
|
|
258593
|
+
async function printStreamUntilEnd(stream, levelFilter, jsonMode, startTime) {
|
|
258594
|
+
let lastTime = startTime;
|
|
258595
|
+
let producedEvents = false;
|
|
258596
|
+
try {
|
|
258597
|
+
for await (const event of stream) {
|
|
258598
|
+
producedEvents = true;
|
|
258599
|
+
if (event.kind === "end")
|
|
258600
|
+
return { lastTime, producedEvents, end: event.end };
|
|
258601
|
+
if (levelFilter && event.log.level !== levelFilter)
|
|
258602
|
+
continue;
|
|
258603
|
+
writeFollowLine(streamEventToLogEntry(event.log), jsonMode);
|
|
258604
|
+
if (event.log.time > lastTime)
|
|
258605
|
+
lastTime = event.log.time;
|
|
258606
|
+
}
|
|
258607
|
+
} catch {}
|
|
258608
|
+
return { lastTime, producedEvents, end: null };
|
|
258609
|
+
}
|
|
258610
|
+
var STREAM_RECONNECT_DELAY_MS = 1000;
|
|
258611
|
+
var MAX_DROPS_SINCE_LAST_EVENT = 2;
|
|
258612
|
+
async function streamUntilExhausted(options, jsonMode) {
|
|
258613
|
+
const filters = {
|
|
258614
|
+
functions: parseFunctionNames(options.function),
|
|
258615
|
+
env: options.env
|
|
258616
|
+
};
|
|
258617
|
+
let everConnected = false;
|
|
258618
|
+
let lastTime = "";
|
|
258619
|
+
let dropsSinceLastEvent = 0;
|
|
258620
|
+
while (true) {
|
|
258621
|
+
const stream = await openLogStream(filters);
|
|
258622
|
+
if (!stream)
|
|
258623
|
+
break;
|
|
258624
|
+
everConnected = true;
|
|
258625
|
+
const ending = await printStreamUntilEnd(stream, options.level, jsonMode, lastTime);
|
|
258626
|
+
lastTime = ending.lastTime;
|
|
258627
|
+
if (ending.end) {
|
|
258628
|
+
if (!ending.end.retriable)
|
|
258629
|
+
break;
|
|
258630
|
+
dropsSinceLastEvent = 0;
|
|
258631
|
+
} else {
|
|
258632
|
+
dropsSinceLastEvent = ending.producedEvents ? 1 : dropsSinceLastEvent + 1;
|
|
258633
|
+
if (dropsSinceLastEvent >= MAX_DROPS_SINCE_LAST_EVENT)
|
|
258634
|
+
break;
|
|
258635
|
+
}
|
|
258636
|
+
await delay2(STREAM_RECONNECT_DELAY_MS);
|
|
258637
|
+
}
|
|
258638
|
+
return { everConnected, lastTime };
|
|
258639
|
+
}
|
|
258640
|
+
async function followLogs(functionNames, options, availableFunctionNames, jsonMode, logger2) {
|
|
258641
|
+
const { everConnected, lastTime } = await streamUntilExhausted(options, jsonMode);
|
|
258642
|
+
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).");
|
|
258643
|
+
return pollLogs(functionNames, options, availableFunctionNames, jsonMode, {
|
|
258644
|
+
lastTime,
|
|
258645
|
+
boundaryKeys: new Set
|
|
258646
|
+
});
|
|
258647
|
+
}
|
|
258648
|
+
async function pollLogs(functionNames, options, availableFunctionNames, jsonMode, initialState) {
|
|
258649
|
+
let state = initialState;
|
|
258650
|
+
let first = state.lastTime === "";
|
|
258460
258651
|
while (true) {
|
|
258461
258652
|
const pollOptions = first ? options : { ...options, since: state.lastTime };
|
|
258462
258653
|
const entries = await fetchLogsForFunctions(functionNames, pollOptions, availableFunctionNames);
|
|
@@ -258466,7 +258657,7 @@ async function followLogs(functionNames, options, availableFunctionNames, jsonMo
|
|
|
258466
258657
|
for (const entry of fresh)
|
|
258467
258658
|
writeFollowLine(entry, jsonMode);
|
|
258468
258659
|
first = false;
|
|
258469
|
-
await
|
|
258660
|
+
await delay2(2000);
|
|
258470
258661
|
}
|
|
258471
258662
|
}
|
|
258472
258663
|
function formatLogs(entries, env3) {
|
|
@@ -258552,6 +258743,9 @@ async function logsAction(ctx, options) {
|
|
|
258552
258743
|
};
|
|
258553
258744
|
}
|
|
258554
258745
|
if (options.follow) {
|
|
258746
|
+
if (options.since) {
|
|
258747
|
+
throw new InvalidInputError("--since cannot be combined with --follow yet (the realtime stream starts from now).");
|
|
258748
|
+
}
|
|
258555
258749
|
if (options.until) {
|
|
258556
258750
|
throw new InvalidInputError("--until cannot be combined with --follow (a stream has no end).");
|
|
258557
258751
|
}
|
|
@@ -258559,7 +258753,7 @@ async function logsAction(ctx, options) {
|
|
|
258559
258753
|
throw new InvalidInputError("--order cannot be combined with --follow (a live tail always streams oldest to newest).");
|
|
258560
258754
|
}
|
|
258561
258755
|
options.order = "asc";
|
|
258562
|
-
return followLogs(functionNames, options, availableFunctionNames, ctx.jsonMode);
|
|
258756
|
+
return followLogs(functionNames, options, availableFunctionNames, ctx.jsonMode, ctx.log);
|
|
258563
258757
|
}
|
|
258564
258758
|
let entries = await fetchLogsForFunctions(functionNames, options, availableFunctionNames);
|
|
258565
258759
|
const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
|
|
@@ -268208,4 +268402,4 @@ export {
|
|
|
268208
268402
|
CLIExitError
|
|
268209
268403
|
};
|
|
268210
268404
|
|
|
268211
|
-
//# debugId=
|
|
268405
|
+
//# debugId=844375621C10BF7464756E2164756E21
|