Skip to content

Commit

Permalink
fix: injected services should not be re-evaluated within the request …
Browse files Browse the repository at this point in the history
…scope (#12)
  • Loading branch information
maou-shonen authored Oct 26, 2024
1 parent 6f2847e commit 47703d3
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
21 changes: 21 additions & 0 deletions src/dependency.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,27 @@ describe("Dependency", () => {
expect(createCount).toBe(2);
});

it("injected service will not be re-evaluated on request scope", async () => {
const dep = new Dependency(() => new TestService("foo"), {
scope: "request",
});
const app = new Hono()
.use(dep.middleware("service"))
.get("/", (c) => c.text(c.var.service.name));

dep.injection(new TestService("bar"));

const res1 = await app.request("/");
expect(res1.status).toBe(200);
const data1 = await res1.text();
expect(data1).toBe("bar");

const res2 = await app.request("/");
expect(res2.status).toBe(200);
const data2 = await res2.text();
expect(data2).toBe("bar");
});

it("clear injected service", async () => {
const dep = new Dependency(() => new TestService("foo"));
const app = new Hono()
Expand Down
16 changes: 10 additions & 6 deletions src/dependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,42 @@ export class Dependency<Service> {
},
) {}

// service cache
private service?: Service;
private serviceInjected?: Service;
private serviceCached?: Service;
// used as a basis for caching when evaluating the request scope
private lastRequest?: Request;

/**
* Injects a service instance directly. Useful for overriding the default service.
*/
injection(service: Service): this {
this.service = service;
this.serviceInjected = service;
return this;
}

/**
* Clear injected service.
*/
clearInjected(): this {
this.service = undefined;
this.serviceInjected = undefined;
return this;
}

/**
* Resolve service.
*/
async resolve(c: Context): Promise<Service> {
if (this.serviceInjected) {
return this.serviceInjected;
}

// evaluate and clear the cache when handling the request scope
if (this.opts?.scope === "request" && this.lastRequest !== c.req.raw) {
this.service = undefined;
this.serviceCached = undefined;
this.lastRequest = c.req.raw;
}

const service = (this.service ??= await this.serviceInitializer(c));
const service = (this.serviceCached ??= await this.serviceInitializer(c));

return service;
}
Expand Down

0 comments on commit 47703d3

Please sign in to comment.