@base44-preview/cli 0.0.45-pr.422.0f6b58f → 0.0.45-pr.424.8513daf

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.
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Deno Function Wrapper
3
+ *
4
+ * This script is executed by Deno to run user functions.
5
+ * It patches Deno.serve to inject a dynamic port before importing the user's function.
6
+ *
7
+ * Environment variables:
8
+ * - FUNCTION_PATH: Absolute path to the user's function entry file
9
+ * - FUNCTION_PORT: Port number for the function to listen on
10
+ * - FUNCTION_NAME: Name of the function (for logging)
11
+ */
12
+
13
+ // Make this file a module for top-level await support
14
+ export {};
15
+
16
+ const functionPath = Deno.env.get("FUNCTION_PATH");
17
+ const port = parseInt(Deno.env.get("FUNCTION_PORT") || "8000", 10);
18
+ const functionName = Deno.env.get("FUNCTION_NAME") || "unknown";
19
+
20
+ if (!functionPath) {
21
+ console.error("[wrapper] FUNCTION_PATH environment variable is required");
22
+ Deno.exit(1);
23
+ }
24
+
25
+ // Store the original Deno.serve
26
+ const originalServe = Deno.serve.bind(Deno);
27
+
28
+ // Patch Deno.serve to inject our port and add onListen callback
29
+ // @ts-expect-error - We're intentionally overriding Deno.serve
30
+ Deno.serve = (
31
+ optionsOrHandler:
32
+ | Deno.ServeOptions
33
+ | Deno.ServeHandler
34
+ | (Deno.ServeOptions & { handler: Deno.ServeHandler }),
35
+ maybeHandler?: Deno.ServeHandler,
36
+ ): Deno.HttpServer<Deno.NetAddr> => {
37
+ const onListen = () => {
38
+ // This message is used by FunctionManager to detect when the function is ready
39
+ console.log(`[${functionName}] Listening on http://localhost:${port}`);
40
+ };
41
+
42
+ // Handle the different Deno.serve signatures:
43
+ // 1. Deno.serve(handler)
44
+ // 2. Deno.serve(options, handler)
45
+ // 3. Deno.serve({ ...options, handler })
46
+ if (typeof optionsOrHandler === "function") {
47
+ // Signature: Deno.serve(handler)
48
+ return originalServe({ port, onListen }, optionsOrHandler);
49
+ }
50
+
51
+ if (maybeHandler) {
52
+ // Signature: Deno.serve(options, handler)
53
+ return originalServe({ ...optionsOrHandler, port, onListen }, maybeHandler);
54
+ }
55
+
56
+ // Signature: Deno.serve({ ...options, handler })
57
+ const options = optionsOrHandler as Deno.ServeOptions & {
58
+ handler: Deno.ServeHandler;
59
+ };
60
+ return originalServe({ ...options, port, onListen });
61
+ };
62
+
63
+ console.log(`[${functionName}] Starting function from ${functionPath}`);
64
+
65
+ // Dynamically import the user's function
66
+ // The function will call Deno.serve which is now patched to use our port
67
+ try {
68
+ await import(functionPath);
69
+ } catch (error) {
70
+ console.error(`[${functionName}] Failed to load function:`, error);
71
+ Deno.exit(1);
72
+ }
package/dist/cli/index.js CHANGED
@@ -238351,6 +238351,61 @@ async function fetchFunctionLogs(functionName, filters = {}) {
238351
238351
  }
238352
238352
  return result.data;
238353
238353
  }
238354
+ function buildStreamQueryString(filters) {
238355
+ const params = new URLSearchParams;
238356
+ if (filters.level) {
238357
+ params.set("level", filters.level);
238358
+ }
238359
+ return params;
238360
+ }
238361
+ async function* streamFunctionLogs(functionName, filters = {}, signal) {
238362
+ const appClient = getAppClient();
238363
+ const searchParams = buildStreamQueryString(filters);
238364
+ let response;
238365
+ try {
238366
+ response = await appClient.get(`functions-mgmt/${encodeURIComponent(functionName)}/logs/stream`, {
238367
+ searchParams,
238368
+ timeout: false,
238369
+ signal
238370
+ });
238371
+ } catch (error48) {
238372
+ throw await ApiError.fromHttpError(error48, `streaming function logs: '${functionName}'`);
238373
+ }
238374
+ if (!response.body) {
238375
+ throw new ApiError("Server returned empty response for log stream");
238376
+ }
238377
+ const reader = response.body.getReader();
238378
+ const decoder = new TextDecoder;
238379
+ let buffer = "";
238380
+ try {
238381
+ while (true) {
238382
+ const { done, value } = await reader.read();
238383
+ if (done)
238384
+ break;
238385
+ buffer += decoder.decode(value, { stream: true });
238386
+ for (let newlineIndex = buffer.indexOf(`
238387
+ `);newlineIndex !== -1; newlineIndex = buffer.indexOf(`
238388
+ `)) {
238389
+ const line = buffer.slice(0, newlineIndex).trimEnd();
238390
+ buffer = buffer.slice(newlineIndex + 1);
238391
+ if (line === "" || line.startsWith(":")) {
238392
+ continue;
238393
+ }
238394
+ if (line.startsWith("data: ")) {
238395
+ const jsonStr = line.slice(6);
238396
+ try {
238397
+ const parsed = FunctionLogEntrySchema.safeParse(JSON.parse(jsonStr));
238398
+ if (parsed.success) {
238399
+ yield parsed.data;
238400
+ }
238401
+ } catch {}
238402
+ }
238403
+ }
238404
+ }
238405
+ } finally {
238406
+ reader.releaseLock();
238407
+ }
238408
+ }
238354
238409
  // src/core/resources/function/config.ts
238355
238410
  import { basename as basename2, dirname as dirname3, join as join5, relative } from "node:path";
238356
238411
  async function readFunctionConfig(configPath) {
@@ -238807,7 +238862,7 @@ function getTemplatesIndexPath() {
238807
238862
  return join8(ASSETS_DIR, "templates", "templates.json");
238808
238863
  }
238809
238864
  function getDenoWrapperPath() {
238810
- return join8(ASSETS_DIR, "deno-runtime", "main.js");
238865
+ return join8(ASSETS_DIR, "deno-runtime", "main.ts");
238811
238866
  }
238812
238867
  function ensureNpmAssets(sourceDir) {
238813
238868
  if (existsSync(ASSETS_DIR))
@@ -246812,141 +246867,6 @@ function getAgentsCommand(context) {
246812
246867
  return new Command("agents").description("Manage project agents").addCommand(getAgentsPushCommand(context)).addCommand(getAgentsPullCommand(context));
246813
246868
  }
246814
246869
 
246815
- // src/core/auth-config/schema.ts
246816
- var GoogleOAuthMode = exports_external.enum(["default", "custom"]);
246817
- var AuthConfigSchema = exports_external.object({
246818
- enable_username_password: exports_external.boolean(),
246819
- enable_google_login: exports_external.boolean(),
246820
- enable_microsoft_login: exports_external.boolean(),
246821
- enable_facebook_login: exports_external.boolean(),
246822
- enable_apple_login: exports_external.boolean(),
246823
- sso_provider_name: exports_external.string().nullable(),
246824
- enable_sso_login: exports_external.boolean(),
246825
- google_oauth_mode: GoogleOAuthMode,
246826
- google_oauth_client_id: exports_external.string().nullable(),
246827
- use_workspace_sso: exports_external.boolean()
246828
- }).transform((data) => ({
246829
- enableUsernamePassword: data.enable_username_password,
246830
- enableGoogleLogin: data.enable_google_login,
246831
- enableMicrosoftLogin: data.enable_microsoft_login,
246832
- enableFacebookLogin: data.enable_facebook_login,
246833
- enableAppleLogin: data.enable_apple_login,
246834
- ssoProviderName: data.sso_provider_name,
246835
- enableSSOLogin: data.enable_sso_login,
246836
- googleOAuthMode: data.google_oauth_mode,
246837
- googleOAuthClientId: data.google_oauth_client_id,
246838
- useWorkspaceSSO: data.use_workspace_sso
246839
- }));
246840
- var AppAuthConfigResponseSchema = exports_external.object({
246841
- auth_config: AuthConfigSchema
246842
- }).transform((data) => ({
246843
- authConfig: data.auth_config
246844
- }));
246845
- function toAuthConfigPayload(config10) {
246846
- return {
246847
- enable_username_password: config10.enableUsernamePassword,
246848
- enable_google_login: config10.enableGoogleLogin,
246849
- enable_microsoft_login: config10.enableMicrosoftLogin,
246850
- enable_facebook_login: config10.enableFacebookLogin,
246851
- enable_apple_login: config10.enableAppleLogin,
246852
- sso_provider_name: config10.ssoProviderName,
246853
- enable_sso_login: config10.enableSSOLogin,
246854
- google_oauth_mode: config10.googleOAuthMode,
246855
- google_oauth_client_id: config10.googleOAuthClientId,
246856
- use_workspace_sso: config10.useWorkspaceSSO
246857
- };
246858
- }
246859
-
246860
- // src/core/auth-config/api.ts
246861
- async function getAuthConfig() {
246862
- const { id } = getAppConfig();
246863
- let response;
246864
- try {
246865
- response = await base44Client.get(`api/apps/${id}`);
246866
- } catch (error48) {
246867
- throw await ApiError.fromHttpError(error48, "fetching auth config");
246868
- }
246869
- const result = AppAuthConfigResponseSchema.safeParse(await response.json());
246870
- if (!result.success) {
246871
- throw new SchemaValidationError("Invalid response from server", result.error);
246872
- }
246873
- return result.data.authConfig;
246874
- }
246875
- async function updateAuthConfig(updates) {
246876
- const current = await getAuthConfig();
246877
- const merged = { ...current, ...updates };
246878
- const { id } = getAppConfig();
246879
- let response;
246880
- try {
246881
- response = await base44Client.put(`api/apps/${id}`, {
246882
- json: { auth_config: toAuthConfigPayload(merged) }
246883
- });
246884
- } catch (error48) {
246885
- throw await ApiError.fromHttpError(error48, "updating auth config");
246886
- }
246887
- const result = AppAuthConfigResponseSchema.safeParse(await response.json());
246888
- if (!result.success) {
246889
- throw new SchemaValidationError("Invalid response from server", result.error);
246890
- }
246891
- return result.data.authConfig;
246892
- }
246893
- function hasAnyLoginMethod(config10) {
246894
- return config10.enableUsernamePassword || config10.enableGoogleLogin || config10.enableMicrosoftLogin || config10.enableFacebookLogin || config10.enableAppleLogin || config10.enableSSOLogin;
246895
- }
246896
- async function updatePasswordAuth(enable) {
246897
- return await updateAuthConfig({ enableUsernamePassword: enable });
246898
- }
246899
- // src/cli/commands/auth/password-login.ts
246900
- async function passwordLoginAction() {
246901
- const current = await runTask("Fetching current auth config", async () => await getAuthConfig());
246902
- const currentStatus = current.enableUsernamePassword ? "enabled" : "disabled";
246903
- R2.info(`Username & password authentication is currently ${currentStatus}.`);
246904
- const shouldEnable = await Re({
246905
- message: "Enable username & password authentication?",
246906
- initialValue: current.enableUsernamePassword
246907
- });
246908
- if (Ct(shouldEnable)) {
246909
- throw new CLIExitError(0);
246910
- }
246911
- if (shouldEnable === current.enableUsernamePassword) {
246912
- return {
246913
- outroMessage: `Username & password authentication is already ${currentStatus}`
246914
- };
246915
- }
246916
- if (!shouldEnable) {
246917
- const configWithoutPassword = {
246918
- ...current,
246919
- enableUsernamePassword: false
246920
- };
246921
- if (!hasAnyLoginMethod(configWithoutPassword)) {
246922
- R2.warn("Disabling password auth will leave no login methods enabled. Users will be locked out.");
246923
- const proceed = await Re({
246924
- message: "Are you sure you want to continue?",
246925
- initialValue: false
246926
- });
246927
- if (Ct(proceed) || !proceed) {
246928
- throw new CLIExitError(0);
246929
- }
246930
- }
246931
- }
246932
- const action = shouldEnable ? "Enabling" : "Disabling";
246933
- await runTask(`${action} username & password authentication`, async () => await updatePasswordAuth(shouldEnable));
246934
- const newStatus = shouldEnable ? "enabled" : "disabled";
246935
- return {
246936
- outroMessage: `Username & password authentication ${newStatus}`
246937
- };
246938
- }
246939
- function getPasswordLoginCommand(context) {
246940
- return new Command("password-login").description("Enable or disable username & password authentication").action(async () => {
246941
- await runCommand(passwordLoginAction, { requireAuth: true }, context);
246942
- });
246943
- }
246944
-
246945
- // src/cli/commands/auth/index.ts
246946
- function getAuthCommand(context) {
246947
- return new Command("auth").description("Manage app authentication settings").addCommand(getPasswordLoginCommand(context));
246948
- }
246949
-
246950
246870
  // src/cli/commands/auth/login.ts
246951
246871
  function getLoginCommand(context) {
246952
246872
  return new Command("login").description("Authenticate with Base44").action(async () => {
@@ -248634,6 +248554,91 @@ function validateLimit(limit) {
248634
248554
  throw new InvalidInputError(`Invalid limit: "${limit}". Must be a number between 1 and 1000.`);
248635
248555
  }
248636
248556
  }
248557
+ function validateTailFlags(options) {
248558
+ if (!options.tail)
248559
+ return;
248560
+ const incompatible = [
248561
+ ["--since", options.since],
248562
+ ["--until", options.until],
248563
+ ["--limit", options.limit],
248564
+ ["--order", options.order]
248565
+ ];
248566
+ for (const [flag, value] of incompatible) {
248567
+ if (value !== undefined) {
248568
+ throw new InvalidInputError(`Cannot use ${flag} with --tail`);
248569
+ }
248570
+ }
248571
+ }
248572
+ function formatStreamEntry(entry, functionName, json2) {
248573
+ if (json2) {
248574
+ return JSON.stringify({
248575
+ source: functionName,
248576
+ time: entry.time,
248577
+ level: entry.level,
248578
+ message: entry.message
248579
+ });
248580
+ }
248581
+ const normalized = normalizeLogEntry(entry, functionName);
248582
+ return formatEntry(normalized);
248583
+ }
248584
+ async function consumeStream(functionName, filters, signal, json2) {
248585
+ try {
248586
+ for await (const entry of streamFunctionLogs(functionName, filters, signal)) {
248587
+ process.stdout.write(`${formatStreamEntry(entry, functionName, json2)}
248588
+ `);
248589
+ }
248590
+ return "ended";
248591
+ } catch (error48) {
248592
+ if (signal.aborted)
248593
+ return "aborted";
248594
+ throw error48;
248595
+ }
248596
+ }
248597
+ async function tailAction(options) {
248598
+ validateTailFlags(options);
248599
+ const specifiedFunctions = parseFunctionNames(options.function);
248600
+ const allProjectFunctions = await getAllFunctionNames();
248601
+ const functionNames = specifiedFunctions.length > 0 ? specifiedFunctions : allProjectFunctions;
248602
+ if (functionNames.length === 0) {
248603
+ return { outroMessage: "No functions found in this project." };
248604
+ }
248605
+ const filters = {};
248606
+ if (options.level) {
248607
+ filters.level = options.level;
248608
+ }
248609
+ const json2 = options.json ?? false;
248610
+ const functionList = functionNames.join(", ");
248611
+ R2.info(`Tailing logs for ${functionList}... (Ctrl+C to stop)`);
248612
+ const controller = new AbortController;
248613
+ const onSigint = () => controller.abort();
248614
+ process.on("SIGINT", onSigint);
248615
+ let userAborted = false;
248616
+ try {
248617
+ if (functionNames.length === 1) {
248618
+ const result = await consumeStream(functionNames[0], filters, controller.signal, json2);
248619
+ userAborted = result === "aborted";
248620
+ } else {
248621
+ const results = await Promise.allSettled(functionNames.map((fn) => consumeStream(fn, filters, controller.signal, json2)));
248622
+ const allFailed = results.every((r) => r.status === "rejected");
248623
+ if (allFailed && !controller.signal.aborted) {
248624
+ const firstError = results.find((r) => r.status === "rejected");
248625
+ throw firstError.reason;
248626
+ }
248627
+ for (let i2 = 0;i2 < results.length; i2++) {
248628
+ const result = results[i2];
248629
+ if (result.status === "rejected" && !controller.signal.aborted) {
248630
+ R2.warn(`Connection lost for function '${functionNames[i2]}'`);
248631
+ }
248632
+ }
248633
+ userAborted = controller.signal.aborted;
248634
+ }
248635
+ } finally {
248636
+ process.removeListener("SIGINT", onSigint);
248637
+ }
248638
+ return {
248639
+ outroMessage: userAborted ? "Stream closed" : "Stream ended"
248640
+ };
248641
+ }
248637
248642
  async function logsAction(options) {
248638
248643
  validateLimit(options.limit);
248639
248644
  const specifiedFunctions = parseFunctionNames(options.function);
@@ -248652,8 +248657,9 @@ async function logsAction(options) {
248652
248657
  return { outroMessage: "Fetched logs", stdout: logsOutput };
248653
248658
  }
248654
248659
  function getLogsCommand(context) {
248655
- 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)").addOption(new Option("--order <order>", "Sort order").choices(["asc", "desc"])).action(async (options) => {
248656
- await runCommand(() => logsAction(options), { requireAuth: true }, context);
248660
+ return new Command("logs").description("Fetch function logs for this app (use --tail to stream in real-time)").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)").addOption(new Option("--order <order>", "Sort order").choices(["asc", "desc"])).option("--json", "Output raw JSON").option("-f, --tail", "Stream logs in real-time").action(async (options) => {
248661
+ const action = options.tail ? () => tailAction(options) : () => logsAction(options);
248662
+ await runCommand(action, { requireAuth: true }, context);
248657
248663
  });
248658
248664
  }
248659
248665
 
@@ -251850,7 +251856,6 @@ function createProgram(context) {
251850
251856
  program2.addCommand(getConnectorsCommand(context));
251851
251857
  program2.addCommand(getFunctionsCommand(context));
251852
251858
  program2.addCommand(getSecretsCommand(context));
251853
- program2.addCommand(getAuthCommand(context));
251854
251859
  program2.addCommand(getSiteCommand(context));
251855
251860
  program2.addCommand(getTypesCommand(context));
251856
251861
  program2.addCommand(getDevCommand(context), { hidden: true });
@@ -256096,4 +256101,4 @@ export {
256096
256101
  CLIExitError
256097
256102
  };
256098
256103
 
256099
- //# debugId=7653CD16B4DE4AF964756E2164756E21
256104
+ //# debugId=FFECB82AD6C33D2764756E2164756E21