Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added packages/cli/.18cb51bffb6ffabb-00000000.bun-build
Binary file not shown.
3 changes: 2 additions & 1 deletion packages/cli/backend-runtime/import-map.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"imports": {
"base44:runtime": "./base44-runtime.ts"
"base44:runtime": "./base44-runtime.ts",
"npm:@base44/sdk": "./vendor/base44-sdk.js"
}
}
3 changes: 3 additions & 0 deletions packages/cli/infra/build-binaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ for (const required of [
"dist/assets/backend-runtime/main.ts",
"dist/assets/backend-runtime/import-map.json",
"dist/assets/backend-runtime/base44-runtime.ts",
// The import map points at this bundle, so a binary built without it would
// only fail once a user actually runs `base44 exec`.
"dist/assets/backend-runtime/vendor/base44-sdk.js",
]) {
if (!existsSync(join(ROOT, required))) {
console.error(
Expand Down
14 changes: 14 additions & 0 deletions packages/cli/infra/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ const copyBackendRuntime = () => {
return outDir;
};

// The Deno wrappers import `npm:@base44/sdk`, which the import map redirects to
// this bundle. Fetching it from a registry at run time fails wherever the
// registry is proxied behind a TLS-intercepting gateway, so it ships with the
// CLI and the SDK version is pinned to the release.
const bundleVendoredSdk = () =>
runBuild({
entrypoints: ["./infra/vendor/base44-sdk.ts"],
outdir: "./dist/assets/backend-runtime/vendor",
// Third-party code the user never debugs through us; the map would add
// ~1MB to the published package for nothing.
sourcemap: "none",
});

// Runtime dependencies of the local workerd function runtime. They cannot be
// bundled (workerd and esbuild ship native binaries; @deno/loader ships WASM),
// so they are real npm `dependencies` resolved from node_modules at runtime —
Expand All @@ -55,6 +68,7 @@ const runAllBuilds = async () => {
external: RUNTIME_EXTERNALS,
});
const backendRuntimePath = copyBackendRuntime();
await bundleVendoredSdk();
return {
cli,
backendRuntimePath,
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/infra/vendor/base44-sdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Bundle entry for the vendored SDK shipped to the Deno runtimes. The exec
// wrapper imports `npm:@base44/sdk`, which the runtime import map redirects
// here so Deno never fetches it from a registry at run time.
export * from "@base44/sdk";
4 changes: 4 additions & 0 deletions packages/cli/src/core/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ function getBackendRuntimeDir(): string {
return join(ASSETS_DIR, "backend-runtime");
}

export function getImportMapPath(): string {
return join(getBackendRuntimeDir(), "import-map.json");
}

export function getDenoWrapperPath(): string {
return join(getBackendRuntimeDir(), "main.ts");
}
Expand Down
16 changes: 14 additions & 2 deletions packages/cli/src/core/exec/run-script.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { spawn } from "node:child_process";
import { copyFileSync, writeFileSync } from "node:fs";
import { file } from "tmp-promise";
import { getExecWrapperPath } from "@/core/assets.js";
import { getExecWrapperPath, getImportMapPath } from "@/core/assets.js";
import { getAppUserToken, getSiteUrl } from "@/core/project/api.js";
import { verifyDenoInstalled } from "@/core/utils/index.js";

Expand Down Expand Up @@ -50,11 +50,23 @@ export async function runScript(
cleanupFns.push(tempWrapper.cleanup);
copyFileSync(getExecWrapperPath(), tempWrapper.path);

// Redirects the wrapper's `npm:@base44/sdk` import to the SDK bundled with
// this release. Its entries resolve relative to the map itself, so it stays
// correct even though the wrapper runs from a temp directory.
const importMapPath = getImportMapPath();

try {
const exitCode = await new Promise<number>((resolvePromise) => {
const child = spawn(
"deno",
["run", "--allow-all", "--node-modules-dir=auto", tempWrapper.path],
[
"run",
"--allow-all",
"--node-modules-dir=auto",
"--import-map",
importMapPath,
tempWrapper.path,
],
{
env: {
...process.env,
Expand Down
Loading