@base44-preview/cli 0.1.5-pr.576.161be22 → 0.1.5-pr.576.58ab8ee

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.
@@ -3,54 +3,60 @@
3
3
  *
4
4
  * Deployed backend functions import this module by its bare specifier
5
5
  * (`import { secrets } from "base44:runtime"`). No such module exists on a
6
- * developer machine, so `deno.json` maps the specifier onto this file and
6
+ * developer machine, so `import-map.json` maps the specifier onto this file and
7
7
  * `base44 dev` hands that import map to the Deno subprocess.
8
8
  *
9
- * The surface mirrors production; the deliberate differences are called out on
10
- * each export below.
9
+ * Like the deployed module, this is only a delegator: it holds no state and
10
+ * reads no environment. Everything is served by the `globalThis.Base44` bridge
11
+ * that the host installs before loading the function — `main.ts` locally, the
12
+ * generated Worker entry when deployed. Keeping the two the same shape means a
13
+ * change to what a secret *is* only touches the host, never this file.
11
14
  */
12
15
 
16
+ /** Contract the host installs on `globalThis.Base44`. */
17
+ export interface Base44Bridge {
18
+ waitUntil(promise: Promise<unknown>): void;
19
+ secrets: { get(name: string): string | undefined };
20
+ }
21
+
22
+ function bridge(): Base44Bridge {
23
+ const installed = (globalThis as { Base44?: Base44Bridge }).Base44;
24
+ if (!installed) {
25
+ throw new Error(
26
+ 'base44:runtime was imported without a Base44 function host. It is only available inside a backend function — "base44 dev" installs the bridge before loading your code.',
27
+ );
28
+ }
29
+ return installed;
30
+ }
31
+
13
32
  /**
14
33
  * App secrets.
15
34
  *
16
- * Deployed, these are read from the Worker env binding of the current request.
17
- * Locally they come from the environment `base44 dev` was started with —
18
- * values stored with `base44 secrets set` are deliberately not fetched, so a
19
- * production secret is never copied onto a developer machine. Export the
20
- * variable in your shell to exercise a function that reads it.
35
+ * Deployed, these come from the Worker env binding of the current request.
36
+ * Locally the host reads them from the environment `base44 dev` was started
37
+ * with, so a production secret is never copied onto a developer machine —
38
+ * export the variable in your shell to exercise a function that reads it.
21
39
  *
22
40
  * Returns `undefined` for an unset name rather than throwing, matching the
23
- * deployed signature. Code that needs a secret should construct inside the
41
+ * deployed signature. Code needing a secret should construct inside the
24
42
  * handler: at module scope a client built from `undefined` throws during boot,
25
43
  * where no try/catch is reached and nothing is logged.
26
44
  */
27
45
  export const secrets: { get(name: string): string | undefined } = {
28
46
  get(name: string): string | undefined {
29
- return Deno.env.get(name);
47
+ return bridge().secrets.get(name);
30
48
  },
31
49
  };
32
50
 
33
- // Holds a strong reference to in-flight work so a floating promise cannot be
34
- // collected before it settles.
35
- const pending = new Set<Promise<unknown>>();
36
-
37
51
  /**
38
52
  * Continue work after the response has been sent.
39
53
  *
40
54
  * Deployed, this rides `ctx.waitUntil` to extend the invocation until the
41
- * promise settles. Locally the function is a long-lived server process, so
42
- * there is nothing to hold open; the promise is tracked only so a rejection is
43
- * reported against the function instead of surfacing as an unhandled
44
- * rejection. Returns the same promise so it composes, as in production.
55
+ * promise settles. Locally the function is a long-lived server process, so the
56
+ * host has nothing to hold open and only reports rejections. Returns the same
57
+ * promise either way, so it composes.
45
58
  */
46
59
  export function waitUntil<T>(promise: Promise<T>): Promise<T> {
47
- const tracked = Promise.resolve(promise)
48
- .catch((error: unknown) => {
49
- console.error("[base44:runtime] waitUntil task failed:", error);
50
- })
51
- .finally(() => {
52
- pending.delete(tracked);
53
- });
54
- pending.add(tracked);
60
+ bridge().waitUntil(promise);
55
61
  return promise;
56
62
  }
@@ -20,6 +20,8 @@
20
20
  // Make this file a module for top-level await support
21
21
  export {};
22
22
 
23
+ import type { Base44Bridge } from "./base44-runtime.ts";
24
+
23
25
  const functionPath = Deno.env.get("FUNCTION_PATH");
24
26
  const port = parseInt(Deno.env.get("FUNCTION_PORT") || "8000", 10);
25
27
  const functionName = Deno.env.get("FUNCTION_NAME") || "unknown";
@@ -81,6 +83,37 @@ Object.defineProperty(Deno, "serve", {
81
83
  configurable: true,
82
84
  });
83
85
 
86
+ // Local stand-in for the bridge the deployed Worker entry installs. It must be
87
+ // in place before the function is imported, because module-scope code may read
88
+ // a secret. Deployed, secrets come from the request's Worker env binding and
89
+ // `waitUntil` rides `ctx.waitUntil`; locally secrets come from this process's
90
+ // environment and the server is long-lived, so there is nothing to hold open —
91
+ // in-flight work is only tracked so a rejection is reported against the
92
+ // function instead of surfacing as an unhandled rejection.
93
+ const inFlight = new Set<Promise<unknown>>();
94
+
95
+ const base44Bridge: Base44Bridge = {
96
+ secrets: {
97
+ get: (name: string) => Deno.env.get(name),
98
+ },
99
+ waitUntil: (promise: Promise<unknown>) => {
100
+ const tracked = Promise.resolve(promise)
101
+ .catch((error: unknown) => {
102
+ console.error(`[${functionName}] waitUntil task failed:`, error);
103
+ })
104
+ .finally(() => {
105
+ inFlight.delete(tracked);
106
+ });
107
+ inFlight.add(tracked);
108
+ },
109
+ };
110
+
111
+ Object.defineProperty(globalThis, "Base44", {
112
+ value: base44Bridge,
113
+ writable: false,
114
+ configurable: true,
115
+ });
116
+
84
117
  type FetchHandler = (req: Request) => Response | Promise<Response>;
85
118
 
86
119
  /**
package/dist/cli/index.js CHANGED
@@ -213884,7 +213884,7 @@ var require_parse_path = __commonJS((exports, module) => {
213884
213884
  var reFirstKey = /^[^\[]*/;
213885
213885
  var reDigitPath = /^\[(\d+)\]/;
213886
213886
  var reNormalPath = /^\[([^\]]+)\]/;
213887
- function parsePath2(key2) {
213887
+ function parsePath(key2) {
213888
213888
  function failure() {
213889
213889
  return [{ type: "object", key: key2, last: true }];
213890
213890
  }
@@ -213925,7 +213925,7 @@ var require_parse_path = __commonJS((exports, module) => {
213925
213925
  tail.last = true;
213926
213926
  return steps;
213927
213927
  }
213928
- module.exports = parsePath2;
213928
+ module.exports = parsePath;
213929
213929
  });
213930
213930
 
213931
213931
  // ../../node_modules/append-field/lib/set-value.js
@@ -213996,10 +213996,10 @@ var require_set_value = __commonJS((exports, module) => {
213996
213996
 
213997
213997
  // ../../node_modules/append-field/index.js
213998
213998
  var require_append_field = __commonJS((exports, module) => {
213999
- var parsePath2 = require_parse_path();
213999
+ var parsePath = require_parse_path();
214000
214000
  var setValue = require_set_value();
214001
214001
  function appendField(store, key2, value) {
214002
- var steps = parsePath2(key2);
214002
+ var steps = parsePath(key2);
214003
214003
  steps.reduce(function(context, step) {
214004
214004
  return setValue(context, step, context[step.key], value);
214005
214005
  }, store);
@@ -214616,7 +214616,7 @@ var require_buffer_list = __commonJS((exports, module) => {
214616
214616
  }
214617
214617
  }, {
214618
214618
  key: "join",
214619
- value: function join27(s5) {
214619
+ value: function join26(s5) {
214620
214620
  if (this.length === 0)
214621
214621
  return "";
214622
214622
  var p4 = this.head;
@@ -218205,7 +218205,7 @@ var require_dist5 = __commonJS((exports, module) => {
218205
218205
  });
218206
218206
  module.exports = __toCommonJS(src_exports);
218207
218207
  var import_promises22 = __require("node:fs/promises");
218208
- var import_node_fs24 = __require("node:fs");
218208
+ var import_node_fs23 = __require("node:fs");
218209
218209
  var DEVIN_LOCAL_PATH = "/opt/.devin";
218210
218210
  var CURSOR2 = "cursor";
218211
218211
  var CURSOR_CLI = "cursor-cli";
@@ -218262,7 +218262,7 @@ var require_dist5 = __commonJS((exports, module) => {
218262
218262
  return { isAgent: true, agent: { name: REPLIT } };
218263
218263
  }
218264
218264
  try {
218265
- await (0, import_promises22.access)(DEVIN_LOCAL_PATH, import_node_fs24.constants.F_OK);
218265
+ await (0, import_promises22.access)(DEVIN_LOCAL_PATH, import_node_fs23.constants.F_OK);
218266
218266
  return { isAgent: true, agent: { name: DEVIN } };
218267
218267
  } catch (error48) {}
218268
218268
  return { isAgent: false, agent: undefined };
@@ -234033,7 +234033,7 @@ function normalizeBase44Env() {
234033
234033
  loadProjectEnvFiles();
234034
234034
 
234035
234035
  // src/cli/index.ts
234036
- import { dirname as dirname25, join as join30 } from "node:path";
234036
+ import { dirname as dirname24, join as join29 } from "node:path";
234037
234037
  import { fileURLToPath as fileURLToPath6 } from "node:url";
234038
234038
 
234039
234039
  // ../../node_modules/@clack/core/dist/index.mjs
@@ -253808,7 +253808,7 @@ async function promptForLinkAction() {
253808
253808
  actionOptions.push({
253809
253809
  value: "choose",
253810
253810
  label: "Link an existing project",
253811
- hint: "Choose from one of your available projects previously created by the Base44 CLI"
253811
+ hint: "Choose from one of your existing Base44 apps"
253812
253812
  });
253813
253813
  const action = await Je({
253814
253814
  message: "How would you like to link this project?",
@@ -253845,8 +253845,8 @@ async function promptForNewProjectDetails() {
253845
253845
  description: result.description ? result.description.trim() : undefined
253846
253846
  };
253847
253847
  }
253848
- async function promptForExistingProject(linkableProjects) {
253849
- const projectOptions = linkableProjects.map((project2) => ({
253848
+ async function promptForExistingProject(projects) {
253849
+ const projectOptions = projects.map((project2) => ({
253850
253850
  value: project2,
253851
253851
  label: project2.name
253852
253852
  }));
@@ -253887,15 +253887,14 @@ async function link(ctx, options, command2) {
253887
253887
  successMessage: "Projects fetched",
253888
253888
  errorMessage: "Failed to fetch projects"
253889
253889
  });
253890
- const linkableProjects = projects.filter((p) => p.isManagedSourceCode !== true);
253891
- if (!linkableProjects.length) {
253890
+ if (!projects.length) {
253892
253891
  return { outroMessage: "No projects available for linking" };
253893
253892
  }
253894
253893
  let linkedAppId;
253895
253894
  if (appId) {
253896
- const project2 = linkableProjects.find((p) => p.id === appId);
253895
+ const project2 = projects.find((p) => p.id === appId);
253897
253896
  if (!project2) {
253898
- throw new InvalidInputError(`App with ID "${appId}" not found or not available for linking.`, {
253897
+ throw new InvalidInputError(`App with ID "${appId}" not found.`, {
253899
253898
  hints: [
253900
253899
  { message: "Check the app ID is correct" },
253901
253900
  {
@@ -253906,7 +253905,7 @@ async function link(ctx, options, command2) {
253906
253905
  }
253907
253906
  linkedAppId = appId;
253908
253907
  } else {
253909
- const selectedProject = await promptForExistingProject(linkableProjects);
253908
+ const selectedProject = await promptForExistingProject(projects);
253910
253909
  linkedAppId = selectedProject.id;
253911
253910
  }
253912
253911
  await runTask2("Linking project...", async () => {
@@ -254951,7 +254950,7 @@ function getWorkspaceCommand() {
254951
254950
  // src/cli/dev/dev-server/main.ts
254952
254951
  var import_cors = __toESM(require_lib4(), 1);
254953
254952
  var import_express6 = __toESM(require_express(), 1);
254954
- import { dirname as dirname23, join as join29 } from "node:path";
254953
+ import { dirname as dirname22, join as join28 } from "node:path";
254955
254954
 
254956
254955
  // ../../node_modules/get-port/index.js
254957
254956
  import net from "node:net";
@@ -255123,79 +255122,8 @@ function createDevLogger(label2, labelColor = theme.styles.dim) {
255123
255122
 
255124
255123
  // src/cli/dev/dev-server/function-manager.ts
255125
255124
  import { spawn as spawn2 } from "node:child_process";
255126
- import { dirname as dirname20, join as join26 } from "node:path";
255127
- import { pathToFileURL as pathToFileURL6 } from "node:url";
255128
-
255129
- // src/cli/dev/dev-server/import-map.ts
255130
- var import_json52 = __toESM(require_lib(), 1);
255131
- import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
255132
- import { dirname as dirname19, join as join25, parse as parsePath } from "node:path";
255125
+ import { dirname as dirname19, join as join25 } from "node:path";
255133
255126
  import { pathToFileURL } from "node:url";
255134
- var DENO_CONFIG_NAMES = ["deno.json", "deno.jsonc"];
255135
- function findDenoConfig(startDir) {
255136
- const { root: root2 } = parsePath(startDir);
255137
- let dir = startDir;
255138
- while (true) {
255139
- for (const name2 of DENO_CONFIG_NAMES) {
255140
- const candidate = join25(dir, name2);
255141
- if (existsSync2(candidate))
255142
- return candidate;
255143
- }
255144
- if (dir === root2)
255145
- return null;
255146
- const parent = dirname19(dir);
255147
- if (parent === dir)
255148
- return null;
255149
- dir = parent;
255150
- }
255151
- }
255152
- function absolutize(value, baseUrl) {
255153
- if (!value.startsWith("./") && !value.startsWith("../"))
255154
- return value;
255155
- return new URL(value, baseUrl).href;
255156
- }
255157
- function absolutizeEntries(entries, baseUrl) {
255158
- return Object.fromEntries(Object.entries(entries).map(([key2, value]) => [
255159
- absolutize(key2, baseUrl),
255160
- absolutize(value, baseUrl)
255161
- ]));
255162
- }
255163
- function readImportMap(filePath) {
255164
- const parsed = import_json52.default.parse(readFileSync3(filePath, "utf-8"));
255165
- if (!parsed || typeof parsed !== "object")
255166
- return {};
255167
- const { imports, scopes } = parsed;
255168
- return { imports, scopes };
255169
- }
255170
- function buildImportMapArg(baseImportMapPath, projectDir) {
255171
- const baseUrl = pathToFileURL(baseImportMapPath).href;
255172
- const base = readImportMap(baseImportMapPath);
255173
- const merged = {
255174
- imports: absolutizeEntries(base.imports ?? {}, baseUrl),
255175
- scopes: {}
255176
- };
255177
- const projectConfigPath = findDenoConfig(projectDir);
255178
- if (projectConfigPath) {
255179
- const projectUrl = pathToFileURL(projectConfigPath).href;
255180
- let project2 = {};
255181
- try {
255182
- project2 = readImportMap(projectConfigPath);
255183
- } catch {
255184
- project2 = {};
255185
- }
255186
- merged.imports = {
255187
- ...absolutizeEntries(project2.imports ?? {}, projectUrl),
255188
- ...merged.imports
255189
- };
255190
- for (const [scope, entries] of Object.entries(project2.scopes ?? {})) {
255191
- merged.scopes[absolutize(scope, projectUrl)] = absolutizeEntries(entries, projectUrl);
255192
- }
255193
- }
255194
- const json3 = JSON.stringify(merged);
255195
- return `data:application/json,${encodeURIComponent(json3)}`;
255196
- }
255197
-
255198
- // src/cli/dev/dev-server/function-manager.ts
255199
255127
  var READY_TIMEOUT = 30000;
255200
255128
 
255201
255129
  class FunctionManager {
@@ -255278,11 +255206,11 @@ class FunctionManager {
255278
255206
  }
255279
255207
  spawnFunction(func, port) {
255280
255208
  this.logger.log(`Spawning function "${func.name}" on port ${port}`);
255281
- const importMapArg = buildImportMapArg(join26(dirname20(this.wrapperPath), "import-map.json"), globalThis.process.cwd());
255282
- const process21 = spawn2("deno", ["run", "--allow-all", "--import-map", importMapArg, this.wrapperPath], {
255209
+ const importMapPath = join25(dirname19(this.wrapperPath), "import-map.json");
255210
+ const process21 = spawn2("deno", ["run", "--allow-all", "--import-map", importMapPath, this.wrapperPath], {
255283
255211
  env: {
255284
255212
  ...globalThis.process.env,
255285
- FUNCTION_PATH: pathToFileURL6(func.entryPath).href,
255213
+ FUNCTION_PATH: pathToFileURL(func.entryPath).href,
255286
255214
  FUNCTION_PORT: String(port),
255287
255215
  FUNCTION_NAME: func.name
255288
255216
  },
@@ -257382,9 +257310,9 @@ class NodeFsHandler {
257382
257310
  if (this.fsw.closed) {
257383
257311
  return;
257384
257312
  }
257385
- const dirname22 = sp2.dirname(file2);
257313
+ const dirname21 = sp2.dirname(file2);
257386
257314
  const basename7 = sp2.basename(file2);
257387
- const parent = this.fsw._getWatchedDir(dirname22);
257315
+ const parent = this.fsw._getWatchedDir(dirname21);
257388
257316
  let prevStats = stats;
257389
257317
  if (parent.has(basename7))
257390
257318
  return;
@@ -257411,7 +257339,7 @@ class NodeFsHandler {
257411
257339
  prevStats = newStats2;
257412
257340
  }
257413
257341
  } catch (error48) {
257414
- this.fsw._remove(dirname22, basename7);
257342
+ this.fsw._remove(dirname21, basename7);
257415
257343
  }
257416
257344
  } else if (parent.has(basename7)) {
257417
257345
  const at13 = newStats.atimeMs;
@@ -258444,8 +258372,8 @@ async function createDevServer(options8) {
258444
258372
  broadcastEntityEvent(io6, appId, entityName, event);
258445
258373
  };
258446
258374
  const base44ConfigWatcher = new WatchBase44({
258447
- functions: join29(dirname23(project2.configPath), project2.functionsDir),
258448
- entities: join29(dirname23(project2.configPath), project2.entitiesDir)
258375
+ functions: join28(dirname22(project2.configPath), project2.functionsDir),
258376
+ entities: join28(dirname22(project2.configPath), project2.entitiesDir)
258449
258377
  }, devLogger);
258450
258378
  base44ConfigWatcher.on("change", async (name2) => {
258451
258379
  try {
@@ -258840,7 +258768,7 @@ var import_detect_agent = __toESM(require_dist5(), 1);
258840
258768
  import { release, type } from "node:os";
258841
258769
 
258842
258770
  // ../../node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
258843
- import { dirname as dirname24, posix, sep } from "path";
258771
+ import { dirname as dirname23, posix, sep } from "path";
258844
258772
  function createModulerModifier() {
258845
258773
  const getModuleFromFileName = createGetModuleFromFilename();
258846
258774
  return async (frames) => {
@@ -258849,7 +258777,7 @@ function createModulerModifier() {
258849
258777
  return frames;
258850
258778
  };
258851
258779
  }
258852
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname24(process.argv[1]) : process.cwd(), isWindows5 = sep === "\\") {
258780
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname23(process.argv[1]) : process.cwd(), isWindows5 = sep === "\\") {
258853
258781
  const normalizedBase = isWindows5 ? normalizeWindowsPath2(basePath) : basePath;
258854
258782
  return (filename) => {
258855
258783
  if (!filename)
@@ -263038,9 +262966,9 @@ function addCommandInfoToErrorReporter(program2, errorReporter) {
263038
262966
  });
263039
262967
  }
263040
262968
  // src/cli/index.ts
263041
- var __dirname4 = dirname25(fileURLToPath6(import.meta.url));
262969
+ var __dirname4 = dirname24(fileURLToPath6(import.meta.url));
263042
262970
  async function runCLI(options8) {
263043
- ensureNpmAssets(join30(__dirname4, "../assets"));
262971
+ ensureNpmAssets(join29(__dirname4, "../assets"));
263044
262972
  const errorReporter = new ErrorReporter;
263045
262973
  errorReporter.registerProcessErrorHandlers();
263046
262974
  const jsonMode = process.argv.includes("--json");
@@ -263079,4 +263007,4 @@ export {
263079
263007
  CLIExitError
263080
263008
  };
263081
263009
 
263082
- //# debugId=81AA053654470EFC64756E2164756E21
263010
+ //# debugId=DEC46CF3A56ABD6664756E2164756E21