Skip to content

Commit 257f6d9

Browse files
committed
fix: make .callable accept cache & context, update docs & tests
Signed-off-by: tunnckoCore <5038030+tunnckoCore@users.noreply.github.com>
1 parent ecda29f commit 257f6d9

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,9 @@ hello('invalid-keys');
382382

383383
In some advanced scenarios, you may need to pass runtime context to handlers, like `req`, `db`, `user`, sessions, and other dependencies. It's fully typed dependency injection mechanism.
384384

385-
You may or may not provide initial context that will be merged with the context you provide through `.callable`
385+
You may or may not provide initial context that will be merged with the context you provide through `.callable({ context })`.
386+
387+
Providing context (and cache for that matter) can be done through the `.callable` method - that's useful for passing it from "execution place", not where you "define" your procedures - like server `Request/Response` (fetch API) handler.
386388

387389
```ts
388390
const procedure = zagora()
@@ -394,7 +396,7 @@ const procedure = zagora()
394396
})
395397
// NOTE: a) you will get intellisense here
396398
// NOTE: b) you can override context
397-
.callable({ userId: 'foo-bar', foo: 'qux' });
399+
.callable({ context: { userId: 'foo-bar', foo: 'qux' } });
398400

399401
procedure('charlie');
400402
// => 'foo-bar has foo -> qux, id = charlie'
@@ -545,7 +547,8 @@ Built-in caching with custom cache adapter. Cache key includes the input, the in
545547
const cache = new Map();
546548

547549
const procedure = zagora()
548-
.cache(cache)
550+
// NOTE: you can either pass through `.cache` or through `.callable({ cache })`
551+
// .cache(cache)
549552
.input(z.string())
550553
// NOTE: the handler is NOT marked as async!
551554
.handler((_, input) => {
@@ -575,6 +578,8 @@ const proc = zagora()
575578
const res = await proc(22);
576579
```
577580

581+
You can also provide the cache through `.callable({ cache })`. That is useful, if you want to provide it at "execution place", not at "definition place". For example, you'd have a set of procedures written at one place, then throgh "router" or some object that combiens them you want to call them at a `Request/Response` server handler.
582+
578583

579584
### Options Object
580585

src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,13 @@ export class Zagora<
318318
callable<
319319
TNewContext extends TContext,
320320
TKindNames extends ResolveErrorKindNames<TErrorsMap>,
321-
>(context?: TNewContext) {
322-
return this._createProcedure<TNewContext, TKindNames>(context);
321+
TNewCacheAdapter extends CacheAdapter,
322+
>(options: { context?: TNewContext; cache?: TNewCacheAdapter } = {}) {
323+
let za = this;
324+
if (options.cache) {
325+
za = this.cache(options.cache) as any;
326+
}
327+
328+
return za._createProcedure<TNewContext, TKindNames>(options.context);
323329
}
324330
}

test/main.test.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ test("context override in callable", () => {
7575
.handler(({ context }, input) => {
7676
return `${input}-${context.db}`;
7777
})
78-
.callable({ db: "override" });
78+
.callable({ context: { db: "override" } });
7979

8080
const res = fn("baz");
8181
if (res.ok) {
@@ -624,3 +624,25 @@ test("basic in-memory caching/memoization", async () => {
624624
const _ = await hello("Bobby");
625625
expect(called, "Expects `called` to be incremented").toBe(2);
626626
});
627+
628+
test("cache adapter passed through `.callable` method", async () => {
629+
let called = 0;
630+
const hello = zagora()
631+
.context({ age: 10 })
632+
.input(z.string())
633+
.handler(({ context }) => {
634+
called += 1;
635+
return context.age + called;
636+
})
637+
.callable({ cache: new Map() });
638+
639+
const res = hello("foo");
640+
expect(res.ok).toBe(true);
641+
expect(called, "expects to be called once").toBe(1);
642+
expect((res as any).data).toStrictEqual(11);
643+
644+
const res2 = hello("foo");
645+
expect(res2.ok).toBe(true);
646+
expect(called, "expects to be called only once").toBe(1);
647+
expect((res2 as any).data).toStrictEqual(11);
648+
});

0 commit comments

Comments
 (0)