@base44-preview/cli 0.1.5-pr.576.161be22 → 0.1.5-pr.576.3ff0d46
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/assets/backend-runtime/base44-runtime.ts +32 -26
- package/dist/assets/backend-runtime/main.ts +33 -0
- package/dist/cli/index.js +4232 -885
- package/dist/cli/index.js.map +26 -8
- package/package.json +6 -1
|
@@ -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 `
|
|
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
|
-
*
|
|
10
|
-
*
|
|
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
|
|
17
|
-
* Locally
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
43
|
-
*
|
|
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
|
-
|
|
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
|
/**
|