-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(tsyringe): add @hono/tsyringe middleware (#785)
- Loading branch information
Showing
9 changed files
with
269 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@hono/tsyringe': major | ||
--- | ||
|
||
add tsyringe middleware support |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: ci-tsyringe | ||
on: | ||
push: | ||
branches: [main] | ||
paths: | ||
- 'packages/tsyringe/**' | ||
pull_request: | ||
branches: ['*'] | ||
paths: | ||
- 'packages/tsyringe/**' | ||
|
||
jobs: | ||
ci: | ||
runs-on: ubuntu-latest | ||
defaults: | ||
run: | ||
working-directory: ./packages/tsyringe | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: 20.x | ||
- run: yarn install --frozen-lockfile | ||
- run: yarn build | ||
- run: yarn test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# tsyringe middleware for Hono | ||
|
||
The [tsyringe](https://github.com/microsoft/tsyringe) middleware provides a way to use dependency injection in [Hono](https://hono.dev/). | ||
|
||
## Usage | ||
|
||
```ts | ||
import "reflect-metadata" // tsyringe requires reflect-metadata or polyfill | ||
import { container, inject, injectable } from 'tsyringe' | ||
import { tsyringe } from '@hono/tsyringe' | ||
import { Hono } from 'hono' | ||
|
||
@injectable() | ||
class Hello { | ||
constructor(@inject('name') private name: string) {} | ||
|
||
greet() { | ||
return `Hello, ${this.name}!` | ||
} | ||
} | ||
|
||
const app = new Hono() | ||
|
||
app.use('*', tsyringe((container) => { | ||
container.register('name', { useValue: 'world' }) | ||
})) | ||
|
||
app.get('/', (c) => { | ||
const hello = container.resolve(Hello) | ||
return c.text(hello.greet()) | ||
}) | ||
|
||
export default app | ||
``` | ||
|
||
### With providers | ||
|
||
```ts | ||
const app = new Hono() | ||
|
||
app.use('/tenant/:name/*', async (c, next) => { | ||
await tsyringe((container) => { | ||
// Allowing to inject `c.var` or `c.req.param` in the providers | ||
const tenantName = c.req.param('name') | ||
|
||
container.register(Config, { useFactory: () => new Config(tenantName) }) | ||
})(c, next) | ||
}) | ||
``` | ||
|
||
## Author | ||
|
||
Aotokitsuruya <https://github.com/elct9620> | ||
|
||
## License | ||
|
||
MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{ | ||
"name": "@hono/tsyringe", | ||
"version": "0.1.0", | ||
"description": "The tsyringe dependency injection middleware for Hono", | ||
"type": "module", | ||
"module": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"test": "vitest --run", | ||
"build": "tsup ./src/index.ts --format esm,cjs --dts", | ||
"publint": "publint", | ||
"release": "yarn build && yarn test && yarn publint && yarn publish" | ||
}, | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
} | ||
}, | ||
"license": "MIT", | ||
"publishConfig": { | ||
"registry": "https://registry.npmjs.org", | ||
"access": "public" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/honojs/middleware.git" | ||
}, | ||
"homepage": "https://github.com/honojs/middleware", | ||
"peerDependencies": { | ||
"hono": ">=4.*", | ||
"tsyringe": ">=4.*" | ||
}, | ||
"devDependencies": { | ||
"hono": "^4.4.12", | ||
"prettier": "^3.3.3", | ||
"reflect-metadata": "^0.2.2", | ||
"tsup": "^8.1.0", | ||
"tsyringe": "^4.8.0", | ||
"vitest": "^1.6.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import 'reflect-metadata' | ||
import { injectable, inject } from 'tsyringe' | ||
import { Hono } from 'hono' | ||
import { tsyringe } from '../src' | ||
|
||
class Config { | ||
constructor(public readonly tenantName: string) {} | ||
} | ||
|
||
@injectable() | ||
class TenantService { | ||
constructor(@inject(Config) public readonly config: Config) {} | ||
|
||
get message() { | ||
return `Hello, ${this.config.tenantName}!` | ||
} | ||
} | ||
|
||
describe('tsyringe middleware', () => { | ||
const app = new Hono() | ||
|
||
app.use( | ||
'/hello/*', | ||
tsyringe((container) => container.register('foo', { useValue: 'Hello!' })) | ||
) | ||
app.get('/hello/foo', (c) => { | ||
const message = c.var.resolve<string>('foo') | ||
return c.text(message) | ||
}) | ||
|
||
app.use('/tenant/:name/*', async (c, next) => { | ||
await tsyringe((container) => { | ||
const tenantName = c.req.param('name') | ||
|
||
container.register(Config, { useFactory: () => new Config(tenantName) }) | ||
})(c, next) | ||
}) | ||
|
||
app.get('/tenant/:name/message', (c) => { | ||
const tenantService = c.var.resolve(TenantService) | ||
return c.text(tenantService.message) | ||
}) | ||
|
||
it('Should be hello message', async () => { | ||
const res = await app.request('http://localhost/hello/foo') | ||
expect(res).not.toBeNull() | ||
expect(res.status).toBe(200) | ||
expect(await res.text()).toBe('Hello!') | ||
}) | ||
|
||
it('Should be tenant message', async () => { | ||
const res = await app.request('http://localhost/tenant/foo/message') | ||
expect(res).not.toBeNull() | ||
expect(res.status).toBe(200) | ||
expect(await res.text()).toBe('Hello, foo!') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { container, DependencyContainer, InjectionToken } from 'tsyringe' | ||
import type { Context, MiddlewareHandler } from 'hono' | ||
import { createMiddleware } from 'hono/factory' | ||
|
||
declare module 'hono' { | ||
interface ContextVariableMap { | ||
resolve: <T>(token: InjectionToken<T>) => T | ||
} | ||
} | ||
|
||
export type Provider = (container: DependencyContainer) => void | ||
export const tsyringe = (...providers: Provider[]): MiddlewareHandler => { | ||
return createMiddleware(async (c, next) => { | ||
const childContainer = container.createChildContainer() | ||
providers.forEach((provider) => provider(childContainer)) | ||
c.set('resolve', <T>(token: InjectionToken<T>) => childContainer.resolve(token)) | ||
await next() | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"rootDir": "./src", | ||
"outDir": "./dist", | ||
"experimentalDecorators": true, | ||
"emitDecoratorMetadata": true | ||
}, | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/// <reference types="vitest" /> | ||
import { defineConfig } from 'vitest/config' | ||
|
||
export default defineConfig({ | ||
test: { | ||
globals: true, | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters