Skip to content

Commit

Permalink
expose no-op caches in getBindingsProxy (#4847)
Browse files Browse the repository at this point in the history
* expose no-op `caches` in getBindingsProxy

---------

Co-authored-by: MrBBot <bcoll@cloudflare.com>
  • Loading branch information
dario-piotrowicz and mrbbot authored Jan 30, 2024
1 parent b92e5ac commit 6968e11
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 7 deletions.
12 changes: 12 additions & 0 deletions .changeset/happy-pandas-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"wrangler": minor
---

feat: expose new (no-op) `caches` field in `getBindingsProxy` result

Add a new `caches` field to the `getBindingsProxy` result, such field implements a
no operation (no-op) implementation of the runtime `caches`

Note: Miniflare exposes a proper `caches` mock, we will want to use that one in
the future but issues regarding it must be ironed out first, so for the
time being a no-op will have to do
3 changes: 2 additions & 1 deletion fixtures/get-bindings-proxy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"devDependencies": {
"@cloudflare/workers-tsconfig": "workspace:*",
"@cloudflare/workers-types": "^4.20221111.1",
"wrangler": "workspace:*"
"wrangler": "workspace:*",
"undici": "^5.28.2"
}
}
34 changes: 34 additions & 0 deletions fixtures/get-bindings-proxy/tests/get-bindings-proxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Fetcher,
R2Bucket,
} from "@cloudflare/workers-types";
import { Request, Response } from "undici";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import {
getBindingsProxy as originalGetBindingsProxy,
Expand Down Expand Up @@ -227,6 +228,25 @@ describe("getBindingsProxy", () => {
await dispose();
}
});

describe("caches", () => {
(["default", "named"] as const).forEach((cacheType) =>
it(`correctly obtains a no-op ${cacheType} cache`, async () => {
const { caches, dispose } = await getBindingsProxy<Bindings>({
configPath: wranglerTomlFilePath,
});
try {
const cache =
cacheType === "default"
? caches.default
: await caches.open("my-cache");
testNoOpCache(cache);
} finally {
await dispose();
}
})
);
});
});

/**
Expand Down Expand Up @@ -263,3 +283,17 @@ async function testDoBinding(
const doRespText = await doResp.text();
expect(doRespText).toBe(expectedResponse);
}

async function testNoOpCache(
cache: Awaited<ReturnType<typeof getBindingsProxy>>["caches"]["default"]
) {
let match = await cache.match("http://0.0.0.0/test");
expect(match).toBeUndefined();

const req = new Request("http://0.0.0.0/test");
await cache.put(req, new Response("test"));
const resp = await cache.match(req);
expect(resp).toBeUndefined();
const deleted = await cache.delete(req);
expect(deleted).toBe(false);
}
62 changes: 62 additions & 0 deletions packages/wrangler/src/api/integrations/bindings/caches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* eslint-disable unused-imports/no-unused-vars */

/**
* Note about this file:
*
* Here we are providing a no-op implementation of the runtime Cache API instead of using
* the miniflare implementation (via `mf.getCaches()`).
*
* We are not using miniflare's implementation because that would require the user to provide
* miniflare-specific Request objects and they would receive back miniflare-specific Response
* objects, this (in particular the Request part) is not really suitable for `getBindingsProxy`
* as people would ideally interact with their bindings in a very production-like manner and
* requiring them to deal with miniflare-specific classes defeats a bit the purpose of the utility.
*
* Similarly the Request and Response types here are set to `undefined` as not to use specific ones
* that would require us to make a choice right now or the user to adapt their code in order to work
* with the api.
*
* We need to find a better/generic manner in which we can reuse the miniflare cache implementation,
* but until then the no-op implementation below will have to do.
*/

/**
* No-op implementation of CacheStorage
*/
export class CacheStorage {
async open(cacheName: string): Promise<Cache> {
return new Cache();
}

get default(): Cache {
return new Cache();
}
}

type CacheRequest = unknown;
type CacheResponse = unknown;

/**
* No-op implementation of Cache
*/
class Cache {
async delete(
request: CacheRequest,
options?: CacheQueryOptions
): Promise<boolean> {
return false;
}

async match(
request: CacheRequest,
options?: CacheQueryOptions
): Promise<CacheResponse | undefined> {
return undefined;
}

async put(request: CacheRequest, response: CacheResponse): Promise<void> {}
}

type CacheQueryOptions = {
ignoreMethod?: boolean;
};
6 changes: 6 additions & 0 deletions packages/wrangler/src/api/integrations/bindings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getBindings } from "../../../dev";
import { getBoundRegisteredWorkers } from "../../../dev-registry";
import { getVarsForDev } from "../../../dev/dev-vars";
import { buildMiniflareBindingOptions } from "../../../dev/miniflare";
import { CacheStorage } from "./caches";
import { getServiceBindings } from "./services";
import type { Config } from "../../../config";
import type { MiniflareOptions } from "miniflare";
Expand Down Expand Up @@ -39,6 +40,10 @@ export type BindingsProxy<Bindings = Record<string, unknown>> = {
* Object containing the various proxies
*/
bindings: Bindings;
/**
* Caches object emulating the Workers Cache runtime API
*/
caches: CacheStorage;
/**
* Function used to dispose of the child process providing the bindings implementation
*/
Expand Down Expand Up @@ -83,6 +88,7 @@ export async function getBindingsProxy<Bindings = Record<string, unknown>>(
...vars,
...bindings,
},
caches: new CacheStorage(),
dispose: () => mf.dispose(),
};
}
Expand Down
15 changes: 9 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6968e11

Please sign in to comment.