diff --git a/.changeset/cyan-pets-prove.md b/.changeset/cyan-pets-prove.md new file mode 100644 index 000000000000..a5f4b1ec7518 --- /dev/null +++ b/.changeset/cyan-pets-prove.md @@ -0,0 +1,5 @@ +--- +"@cloudflare/vite-plugin": minor +--- + +add a `remoteBindings` option to allow the disabling of remote bindings diff --git a/.changeset/modern-foxes-dream.md b/.changeset/modern-foxes-dream.md new file mode 100644 index 000000000000..b1eaedd33011 --- /dev/null +++ b/.changeset/modern-foxes-dream.md @@ -0,0 +1,5 @@ +--- +"wrangler": minor +--- + +add a `remoteBindings` option to `getPlatformProxy` to allow the disabling of remote bindings diff --git a/.changeset/shy-teams-appear.md b/.changeset/shy-teams-appear.md new file mode 100644 index 000000000000..18955de15d25 --- /dev/null +++ b/.changeset/shy-teams-appear.md @@ -0,0 +1,5 @@ +--- +"wrangler": patch +--- + +Update the description of the `--local` flag for the `wrangler dev` command to clarify that it disables remote bindings, also un-deprecate and un-hide it diff --git a/.changeset/thirty-lights-build.md b/.changeset/thirty-lights-build.md new file mode 100644 index 000000000000..7be6d836a3ed --- /dev/null +++ b/.changeset/thirty-lights-build.md @@ -0,0 +1,5 @@ +--- +"wrangler": patch +--- + +Fix bindings with `remote: true` being logged as `remote` when run via `wrangler dev --local` diff --git a/fixtures/get-platform-proxy-remote-bindings/tests/remote-bindings-false.test.ts b/fixtures/get-platform-proxy-remote-bindings/tests/remote-bindings-false.test.ts new file mode 100644 index 000000000000..a1ebbb1cfea0 --- /dev/null +++ b/fixtures/get-platform-proxy-remote-bindings/tests/remote-bindings-false.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, test } from "vitest"; +import { getPlatformProxy } from "wrangler"; +import type { Ai } from "@cloudflare/workers-types/experimental"; + +describe("getPlatformProxy - remote bindings with remoteBindings: false", () => { + test("getPlatformProxy works with remote bindings", async () => { + const { env, dispose } = await getPlatformProxy<{ + AI: Ai; + }>({ + configPath: "./wrangler.remote-bindings-false.jsonc", + remoteBindings: false, + }); + + await expect( + env.AI.run("@cf/meta/llama-3.1-8b-instruct-fp8", { + messages: [], + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `[Error: Binding AI needs to be run remotely]` + ); + + await dispose(); + }); +}); diff --git a/fixtures/get-platform-proxy-remote-bindings/wrangler.remote-bindings-false.jsonc b/fixtures/get-platform-proxy-remote-bindings/wrangler.remote-bindings-false.jsonc new file mode 100644 index 000000000000..2bb0fec3eb3b --- /dev/null +++ b/fixtures/get-platform-proxy-remote-bindings/wrangler.remote-bindings-false.jsonc @@ -0,0 +1,8 @@ +{ + "name": "get-platform-proxy-remote-bindings-with-local-bindings-only-test", + "compatibility_date": "2025-05-07", + "ai": { + "binding": "AI", + "remote": true, + }, +} diff --git a/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/package.json b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/package.json new file mode 100644 index 000000000000..591de74a3cf7 --- /dev/null +++ b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/package.json @@ -0,0 +1,25 @@ +{ + "name": "@cloudflare/vite-plugin-e2e-remote-bindings-disabled", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "buildAndPreview": "vite build && vite preview", + "dev": "vite", + "lint": "eslint .", + "preview": "vite preview" + }, + "devDependencies": { + "@cloudflare/vite-plugin": "*", + "@cloudflare/workers-types": "^4.20250204.0", + "@eslint/js": "^9.19.0", + "eslint": "^9.19.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.18", + "globals": "^15.14.0", + "typescript": "~5.7.2", + "typescript-eslint": "^8.22.0", + "vite": "^6.1.0" + } +} diff --git a/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/src/index.ts b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/src/index.ts new file mode 100644 index 000000000000..affa0959b62b --- /dev/null +++ b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/src/index.ts @@ -0,0 +1,11 @@ +export default { + async fetch(_req, env) { + const content = await env.AI.run("@cf/meta/llama-2-7b-chat-fp16", { + messages: [], + }); + + return Response.json({ + response: content.response, + }); + }, +} satisfies ExportedHandler<{ AI: Ai }>; diff --git a/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.json b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.json new file mode 100644 index 000000000000..b52af703bdc2 --- /dev/null +++ b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.worker.json" } + ] +} diff --git a/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.node.json b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.node.json new file mode 100644 index 000000000000..50130b3a269b --- /dev/null +++ b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.worker.json b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.worker.json new file mode 100644 index 000000000000..ff69f9652d65 --- /dev/null +++ b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/tsconfig.worker.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.node.json", + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo", + "types": ["@cloudflare/workers-types/2023-07-01", "vite/client"] + }, + "include": ["src"] +} diff --git a/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/vite.config.ts b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/vite.config.ts new file mode 100644 index 000000000000..f21a06878871 --- /dev/null +++ b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/vite.config.ts @@ -0,0 +1,13 @@ +import { cloudflare } from "@cloudflare/vite-plugin"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [ + cloudflare({ + configPath: "./wrangler.jsonc", + inspectorPort: false, + remoteBindings: false, + persistState: false, + }), + ], +}); diff --git a/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/wrangler.jsonc b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/wrangler.jsonc new file mode 100644 index 000000000000..01ac9fbff248 --- /dev/null +++ b/packages/vite-plugin-cloudflare/e2e/fixtures/remote-bindings-disabled/wrangler.jsonc @@ -0,0 +1,10 @@ +{ + "name": "cloudflare-vite-e2e-remote-bindings-disabled", + "main": "./src/index.ts", + "compatibility_date": "2024-12-30", + "compatibility_flags": ["nodejs_compat"], + "ai": { + "binding": "AI", + "remote": true, + }, +} diff --git a/packages/vite-plugin-cloudflare/e2e/remote-bindings.test.ts b/packages/vite-plugin-cloudflare/e2e/remote-bindings.test.ts index 95d9d4e4a491..d73b73a573d6 100644 --- a/packages/vite-plugin-cloudflare/e2e/remote-bindings.test.ts +++ b/packages/vite-plugin-cloudflare/e2e/remote-bindings.test.ts @@ -138,3 +138,28 @@ if (!process.env.CLOUDFLARE_ACCOUNT_ID || !process.env.CLOUDFLARE_API_TOKEN) { }); }); } + +describe("remote bindings disabled", () => { + const projectPath = seed("remote-bindings-disabled", "pnpm"); + + describe.each(commands)('with "%s" command', (command) => { + // On Windows the path for the miniflare dependency gets pretty long and this fails in node < 22.7 + // (see: https://github.com/shellscape/jsx-email/issues/225#issuecomment-2420567832), so + // we need to skip this on windows since in CI we're using node 20 + // we should look into re-enable this once we can move to a node a newer version of node + test.skipIf(process.platform === "win32")( + "cannot connect to remote bindings", + async ({ expect }) => { + const proc = await runLongLived("pnpm", command, projectPath); + const url = await waitForReady(proc); + + const response = await fetch(url); + + const responseText = await response.text(); + + expect(responseText).toContain("Error"); + expect(responseText).toContain("Binding AI needs to be run remotely"); + } + ); + }); +}); diff --git a/packages/vite-plugin-cloudflare/src/miniflare-options.ts b/packages/vite-plugin-cloudflare/src/miniflare-options.ts index ac34f68ef9c7..fc1f08d61ea4 100644 --- a/packages/vite-plugin-cloudflare/src/miniflare-options.ts +++ b/packages/vite-plugin-cloudflare/src/miniflare-options.ts @@ -413,13 +413,16 @@ export async function getDevMiniflareOptions(config: { : undefined; const remoteProxySessionData = - await maybeStartOrUpdateRemoteProxySession( - { - name: workerConfig.name, - bindings: bindings ?? {}, - }, - preExistingRemoteProxySession ?? null - ); + !resolvedPluginConfig.remoteBindings + ? // if remote bindings are not enabled then the proxy session can simply be null + null + : await maybeStartOrUpdateRemoteProxySession( + { + name: workerConfig.name, + bindings: bindings ?? {}, + }, + preExistingRemoteProxySession ?? null + ); if (workerConfig.configPath && remoteProxySessionData) { remoteProxySessionsDataMap.set( @@ -738,14 +741,16 @@ export async function getPreviewMiniflareOptions(config: { ? remoteProxySessionsDataMap.get(workerConfig.configPath) : undefined; - const remoteProxySessionData = - await maybeStartOrUpdateRemoteProxySession( - { - name: workerConfig.name, - bindings: bindings ?? {}, - }, - preExistingRemoteProxySessionData ?? null - ); + const remoteProxySessionData = !resolvedPluginConfig.remoteBindings + ? // if remote bindings are not enabled then the proxy session can simply be null + null + : await maybeStartOrUpdateRemoteProxySession( + { + name: workerConfig.name, + bindings: bindings ?? {}, + }, + preExistingRemoteProxySessionData ?? null + ); if (workerConfig.configPath && remoteProxySessionData) { remoteProxySessionsDataMap.set( diff --git a/packages/vite-plugin-cloudflare/src/plugin-config.ts b/packages/vite-plugin-cloudflare/src/plugin-config.ts index a9b9ce43456d..7c06fc1a089e 100644 --- a/packages/vite-plugin-cloudflare/src/plugin-config.ts +++ b/packages/vite-plugin-cloudflare/src/plugin-config.ts @@ -41,6 +41,7 @@ export interface PluginConfig extends EntryWorkerConfig { auxiliaryWorkers?: AuxiliaryWorkerConfig[]; persistState?: PersistState; inspectorPort?: number | false; + remoteBindings?: boolean; experimental?: Experimental; } @@ -58,6 +59,7 @@ interface BaseResolvedConfig { persistState: PersistState; inspectorPort: number | false | undefined; experimental: Experimental; + remoteBindings: boolean; } export interface AssetsOnlyResolvedConfig extends BaseResolvedConfig { @@ -123,6 +125,7 @@ export function resolvePluginConfig( if (viteEnv.isPreview) { return { ...shared, + remoteBindings: pluginConfig.remoteBindings ?? true, type: "preview", workers: getWorkerConfigs(root), }; @@ -151,6 +154,7 @@ export function resolvePluginConfig( cloudflareEnv, config: entryWorkerResolvedConfig.config, configPaths, + remoteBindings: pluginConfig.remoteBindings ?? true, rawConfigs: { entryWorker: entryWorkerResolvedConfig, }, @@ -231,6 +235,7 @@ export function resolvePluginConfig( entryWorkerEnvironmentName, nodeJsCompatMap, staticRouting, + remoteBindings: pluginConfig.remoteBindings ?? true, rawConfigs: { entryWorker: entryWorkerResolvedConfig, auxiliaryWorkers: auxiliaryWorkersResolvedConfigs, diff --git a/packages/wrangler/e2e/remote-binding/dev-remote-bindings.test.ts b/packages/wrangler/e2e/remote-binding/dev-remote-bindings.test.ts index ede17096be3c..ce02560e4973 100644 --- a/packages/wrangler/e2e/remote-binding/dev-remote-bindings.test.ts +++ b/packages/wrangler/e2e/remote-binding/dev-remote-bindings.test.ts @@ -174,30 +174,17 @@ describe.skipIf(!CLOUDFLARE_ACCOUNT_ID)( ); // This should only include logs from the user Wrangler session (i.e. a single list of attached bindings, and only one ready message) - // Logs order are not deterministic, so we match against to possible outputs. - const output1 = dedent` - Your Worker has access to the following bindings: - Binding Resource Mode - env.AI AI remote - ▲ [WARNING] AI bindings always access remote resources, and so may incur usage charges even in local dev. To suppress this warning, set \`remote: true\` for the binding definition in your configuration file. - ⎔ Starting local server... - [wrangler:info] Ready on http://: - [wrangler:info] GET / 200 OK (TIMINGS)`; - - const output2 = dedent` - Your Worker has access to the following bindings: - Binding Resource Mode - env.AI AI remote - ▲ [WARNING] AI bindings always access remote resources, and so may incur usage charges even in local dev. To suppress this warning, set \`remote: true\` for the binding definition in your configuration file. - ⎔ Starting local server... - [wrangler:info] Ready on http://: - [wrangler:info] GET / 200 OK (TIMINGS)`; - const normalizedOutput = normalizeOutput(worker.currentOutput); - expect( - normalizedOutput === output1 || normalizedOutput === output2 - ).toEqual(true); + expect(normalizedOutput).toMatchInlineSnapshot(` + "Your Worker has access to the following bindings: + Binding Resource Mode + env.AI AI remote + ▲ [WARNING] AI bindings always access remote resources, and so may incur usage charges even in local dev. To suppress this warning, set \`remote: true\` for the binding definition in your configuration file. + ⎔ Starting local server... + [wrangler:info] Ready on http://: + [wrangler:info] GET / 200 OK (TIMINGS)" + `); }); describe("shows helpful error logs", () => { diff --git a/packages/wrangler/e2e/remote-binding/start-worker-remote-bindings.test.ts b/packages/wrangler/e2e/remote-binding/start-worker-remote-bindings.test.ts index 826dd955a882..fce0bc481093 100644 --- a/packages/wrangler/e2e/remote-binding/start-worker-remote-bindings.test.ts +++ b/packages/wrangler/e2e/remote-binding/start-worker-remote-bindings.test.ts @@ -124,3 +124,36 @@ describe.skipIf(!CLOUDFLARE_ACCOUNT_ID)("startWorker - remote bindings", () => { await worker.dispose(); }); }); + +it("doesn't connect to remote bindings when `remote` is set to `false`", async () => { + const helper = new WranglerE2ETestHelper(); + await helper.seed(resolve(__dirname, "./workers")); + await helper.seed({ + "wrangler.json": JSON.stringify({ + name: "remote-bindings-test", + main: "ai.js", + compatibility_date: "2025-05-07", + ai: { + binding: "AI", + remote: true, + }, + }), + }); + + await expect(async () => { + const worker = await startWorker({ + config: `${helper.tmpPath}/wrangler.json`, + dev: { + inspector: false, + server: { port: 0 }, + remote: false, + }, + }); + + await worker.ready; + + await worker.fetch("http://example.com"); + }).rejects.toThrowErrorMatchingInlineSnapshot( + `[Error: Binding AI needs to be run remotely]` + ); +}); diff --git a/packages/wrangler/src/__tests__/dev/remote-bindings.test.ts b/packages/wrangler/src/__tests__/dev/remote-bindings.test.ts index ec55d2fc5ed3..d01d25911a04 100644 --- a/packages/wrangler/src/__tests__/dev/remote-bindings.test.ts +++ b/packages/wrangler/src/__tests__/dev/remote-bindings.test.ts @@ -653,6 +653,18 @@ describe("dev with remote bindings", { sequential: true }, () => { await vi.waitFor(() => expect(std.out).toMatch(/Ready/), { timeout: 2_000, }); + const bindingsPrintStart = std.out.indexOf( + "Your Worker has access to the following bindings:" + ); + const bindingsPrintEnd = std.out.indexOf("⎔ Starting local server...") - 1; + expect(std.out.slice(bindingsPrintStart, bindingsPrintEnd)) + .toMatchInlineSnapshot(` + "Your Worker has access to the following bindings: + Binding Resource Mode + env.KV_LOCAL_BINDING (mock-kv-namespace) KV Namespace local + env.KV_REMOTE_BINDING (mock-kv-namespace) KV Namespace local + " + `); expect(proxyWorkerBindings).toEqual(undefined); expect(workerOptions).toEqual([ expect.objectContaining({ diff --git a/packages/wrangler/src/api/integrations/platform/index.ts b/packages/wrangler/src/api/integrations/platform/index.ts index 20cdf6f58a92..c79e3f9cde3f 100644 --- a/packages/wrangler/src/api/integrations/platform/index.ts +++ b/packages/wrangler/src/api/integrations/platform/index.ts @@ -85,6 +85,10 @@ export type GetPlatformProxyOptions = { * If `false` is specified no data is persisted on the filesystem. */ persist?: boolean | { path: string }; + /** + * Whether remote bindings should be enabled or not (defaults to `true`) + */ + remoteBindings?: boolean; }; /** @@ -138,7 +142,7 @@ export async function getPlatformProxy< }); let remoteProxySession: RemoteProxySession | undefined = undefined; - if (config.configPath) { + if (config.configPath && options.remoteBindings !== false) { remoteProxySession = ( (await maybeStartOrUpdateRemoteProxySession({ path: config.configPath, diff --git a/packages/wrangler/src/api/startDevWorker/ConfigController.ts b/packages/wrangler/src/api/startDevWorker/ConfigController.ts index 83a10f20c61c..8fe09e903e8c 100644 --- a/packages/wrangler/src/api/startDevWorker/ConfigController.ts +++ b/packages/wrangler/src/api/startDevWorker/ConfigController.ts @@ -218,6 +218,7 @@ async function resolveBindings( { registry, local: !input.dev?.remote, + remoteBindingsDisabled: input.dev?.remote === false, name: config.name, } ); diff --git a/packages/wrangler/src/dev.ts b/packages/wrangler/src/dev.ts index e5fc48143cbc..e0ff9cc22dfe 100644 --- a/packages/wrangler/src/dev.ts +++ b/packages/wrangler/src/dev.ts @@ -214,10 +214,8 @@ export const dev = createCommand({ }, local: { alias: "l", - describe: "Run on my machine", + describe: "Run locally with remote bindings disabled", type: "boolean", - deprecated: true, - hidden: true, }, minify: { describe: "Minify the script", @@ -454,7 +452,6 @@ export function getInferredHost( * If `undefined` it defaults to the standard .env files from `getDefaultEnvFiles()`. * @param local Whether the dev server should run locally. * @param args Additional arguments for the dev server. - * @param remoteBindingsEnabled Whether remote bindings are enabled, defaults to the value of the `REMOTE_BINDINGS` flag. * @returns The bindings for the Cloudflare Worker. */ export function getBindings( diff --git a/packages/wrangler/src/dev/start-dev.ts b/packages/wrangler/src/dev/start-dev.ts index b5bae8b1b3a8..730d52a6f5e1 100644 --- a/packages/wrangler/src/dev/start-dev.ts +++ b/packages/wrangler/src/dev/start-dev.ts @@ -247,8 +247,12 @@ async function setupDevEnv( }, dev: { auth, - remote: - args.remote || (args.forceLocal || args.local ? false : undefined), + remote: args.enablePagesAssetsServiceBinding + ? // When running `wrangler pages dev` we want `remote` to be `undefined` since that's the + // only supported mode for pages (note: we can't set it to `false` as that would break + // the AI binding) + undefined + : args.remote || (args.forceLocal || args.local ? false : undefined), server: { hostname: args.ip, port: args.port, diff --git a/packages/wrangler/src/utils/print-bindings.ts b/packages/wrangler/src/utils/print-bindings.ts index 37c4e654816e..c5711d26e095 100644 --- a/packages/wrangler/src/utils/print-bindings.ts +++ b/packages/wrangler/src/utils/print-bindings.ts @@ -16,6 +16,7 @@ export function printBindings( context: { registry?: WorkerRegistry | null; local?: boolean; + remoteBindingsDisabled?: boolean; name?: string; provisioning?: boolean; warnIfNoBindings?: boolean; @@ -139,7 +140,8 @@ export function printBindings( type: friendlyBindingNames.workflows, value: value, mode: getMode({ - isSimulatedLocally: script_name ? !remote : true, + isSimulatedLocally: + script_name && !context.remoteBindingsDisabled ? !remote : true, }), }; }) @@ -154,7 +156,7 @@ export function printBindings( type: friendlyBindingNames.kv_namespaces, value: id, mode: getMode({ - isSimulatedLocally: !remote, + isSimulatedLocally: context.remoteBindingsDisabled || !remote, }), }; }) @@ -189,7 +191,8 @@ export function printBindings( type: friendlyBindingNames.send_email, value, mode: getMode({ - isSimulatedLocally: !emailBinding.remote, + isSimulatedLocally: + context.remoteBindingsDisabled || !emailBinding.remote, }), }; }) @@ -204,7 +207,7 @@ export function printBindings( type: friendlyBindingNames.queues, value: queue_name, mode: getMode({ - isSimulatedLocally: !remote, + isSimulatedLocally: context.remoteBindingsDisabled || !remote, }), }; }) @@ -230,7 +233,7 @@ export function printBindings( name: binding, type: friendlyBindingNames.d1_databases, mode: getMode({ - isSimulatedLocally: !remote, + isSimulatedLocally: context.remoteBindingsDisabled || !remote, }), value, }; @@ -247,7 +250,8 @@ export function printBindings( type: friendlyBindingNames.vectorize, value: index_name, mode: getMode({ - isSimulatedLocally: remote ? false : undefined, + isSimulatedLocally: + remote && !context.remoteBindingsDisabled ? false : undefined, }), }; }) @@ -274,7 +278,10 @@ export function printBindings( name: binding, type: friendlyBindingNames.vpc_services, value: service_id, - mode: getMode({ isSimulatedLocally: remote ? false : undefined }), + mode: getMode({ + isSimulatedLocally: + remote && !context.remoteBindingsDisabled ? false : undefined, + }), }; }) ); @@ -295,7 +302,7 @@ export function printBindings( type: friendlyBindingNames.r2_buckets, value: value, mode: getMode({ - isSimulatedLocally: !remote, + isSimulatedLocally: context.remoteBindingsDisabled || !remote, }), }; }) @@ -418,7 +425,7 @@ export function printBindings( type: friendlyBindingNames.browser, value: undefined, mode: getMode({ - isSimulatedLocally: !browser.remote, + isSimulatedLocally: context.remoteBindingsDisabled || !browser.remote, }), }); } @@ -429,7 +436,7 @@ export function printBindings( type: friendlyBindingNames.images, value: undefined, mode: getMode({ - isSimulatedLocally: !images.remote, + isSimulatedLocally: context.remoteBindingsDisabled || !images.remote, }), }); } @@ -441,7 +448,8 @@ export function printBindings( value: undefined, mode: getMode({ isSimulatedLocally: - media.remote === true || media.remote === undefined + (media.remote === true || media.remote === undefined) && + !context.remoteBindingsDisabled ? false : undefined, }), @@ -455,7 +463,10 @@ export function printBindings( value: ai.staging ? `staging` : undefined, mode: getMode({ isSimulatedLocally: - ai.remote === true || ai.remote === undefined ? false : undefined, + (ai.remote === true || ai.remote === undefined) && + !context.remoteBindingsDisabled + ? false + : undefined, }), }); } @@ -467,7 +478,7 @@ export function printBindings( type: friendlyBindingNames.pipelines, value: pipeline, mode: getMode({ - isSimulatedLocally: !remote, + isSimulatedLocally: context.remoteBindingsDisabled || !remote, }), })) ); @@ -561,7 +572,8 @@ export function printBindings( ? `${namespace} (outbound -> ${outbound.service})` : namespace, mode: getMode({ - isSimulatedLocally: remote ? false : undefined, + isSimulatedLocally: + remote && !context.remoteBindingsDisabled ? false : undefined, }), }; }) @@ -576,7 +588,8 @@ export function printBindings( type: friendlyBindingNames.mtls_certificates, value: certificate_id, mode: getMode({ - isSimulatedLocally: remote ? false : undefined, + isSimulatedLocally: + remote && !context.remoteBindingsDisabled ? false : undefined, }), }; })