Skip to content

Commit 6a599d7

Browse files
author
Maciej Łyskawiński
committed
feat(hono-decorators): initial release
1 parent 92f44e1 commit 6a599d7

20 files changed

+417
-33
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"chalk": "4",
1313
"class-transformer": "^0.5.1",
1414
"commander": "^10.0.0",
15+
"hono": "^4.7.9",
1516
"joi": "^17.13.3",
1617
"nx": "15.5.3",
1718
"radash": "^11.0.0",

packages/hono-decorators/.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": [["@nrwl/web/babel", { "useBuiltIns": "usage" }]]
3+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"extends": ["../../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {}
8+
},
9+
{
10+
"files": ["*.ts", "*.tsx"],
11+
"rules": {}
12+
},
13+
{
14+
"files": ["*.js", "*.jsx"],
15+
"rules": {}
16+
}
17+
]
18+
}

packages/hono-decorators/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# hono-decorators-hono-decorators
2+
3+
This library was generated with [Nx](https://nx.dev).
4+
5+
## Running unit tests
6+
7+
Run `nx test hono-decorators-hono-decorators` to execute the unit tests via [Jest](https://jestjs.io).
8+
9+
## Running lint
10+
11+
Run `nx lint hono-decorators-hono-decorators` to execute the lint via [ESLint](https://eslint.org/).
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'hono-decorators-hono-decorators',
4+
preset: '../../../jest.preset.js',
5+
globals: {
6+
'ts-jest': {
7+
tsconfig: '<rootDir>/tsconfig.spec.json',
8+
},
9+
},
10+
testEnvironment: 'node',
11+
transform: {
12+
'^.+\\.[tj]sx?$': 'ts-jest',
13+
},
14+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
15+
coverageDirectory:
16+
'../../../coverage/packages/hono-decorators',
17+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "@longucodes/hono-decorators",
3+
"version": "0.0.1",
4+
"dependencies": {
5+
"hono": "~4.7.9"
6+
},
7+
"repository": {
8+
"url": "https://github.com/LonguCodes/packages",
9+
"type": "git",
10+
"directory": "packages/hono-decorators"
11+
},
12+
"homepage": "https://github.com/LonguCodes/packages/tree/master/packages/hono-decorators",
13+
"bugs": {
14+
"url": "https://github.com/LonguCodes/packages/issues"
15+
},
16+
"license": "MIT"
17+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"name": "hono-decorators",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "packages/hono-decorators/src",
5+
"projectType": "library",
6+
"targets": {
7+
"lint": {
8+
"executor": "@nrwl/linter:eslint",
9+
"outputs": ["{options.outputFile}"],
10+
"options": {
11+
"lintFilePatterns": ["packages/hono-decorators/**/*.ts"]
12+
}
13+
},
14+
"test": {
15+
"executor": "@nrwl/jest:jest",
16+
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
17+
"options": {
18+
"jestConfig": "packages/hono-decorators/jest.config.ts",
19+
"passWithNoTests": true
20+
}
21+
},
22+
"build": {
23+
"executor": "@nrwl/js:tsc",
24+
"outputs": ["{options.outputPath}"],
25+
"options": {
26+
"outputPath": "dist/packages/hono-decorators",
27+
"tsConfig": "packages/hono-decorators/tsconfig.lib.json",
28+
"packageJson": "packages/hono-decorators/package.json",
29+
"main": "packages/hono-decorators/src/index.ts",
30+
"assets": ["packages/hono-decorators/*.md"]
31+
}
32+
},
33+
"publish": {
34+
"executor": "@longucodes/nx-package-builder:build-and-publish",
35+
"options": {
36+
"publishCli": "yarn",
37+
"publishArgs": [
38+
{
39+
"name": "access",
40+
"value": "public"
41+
},
42+
{
43+
"name": "no-git-tag-version"
44+
},
45+
{
46+
"name": "no-commit-hooks"
47+
}
48+
]
49+
}
50+
},
51+
"ci": {
52+
"executor": "@longucodes/nx-package-builder:ci",
53+
"options": {
54+
"noCiMessage": "[skip ci]"
55+
}
56+
}
57+
},
58+
"tags": []
59+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
export const INJECT_METADATA_KEY = Symbol('inject-metadata')
3+
export function Inject(typeOrToken?: unknown){
4+
return (target: any, property: string|symbol) => {
5+
typeOrToken ??= Reflect.getMetadata('design:type',target,property );
6+
if(!typeOrToken || typeOrToken === Object)
7+
return;
8+
const currentMetadata = Reflect.getMetadata(INJECT_METADATA_KEY, target.constructor) ??{};
9+
currentMetadata[property] = typeOrToken;
10+
Reflect.defineMetadata(INJECT_METADATA_KEY, currentMetadata, target.constructor);
11+
}
12+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type {Type} from "../types.ts";
2+
import {isConstructor} from "../type-checks.ts";
3+
import { v4 } from "uuid";
4+
import {INJECT_METADATA_KEY} from "./decorators.ts";
5+
6+
const DI_TOKEN = Symbol("di-token");
7+
8+
export class DIStore {
9+
10+
private _instances = new Map<string, any>();
11+
12+
public getInstance<T>(clsOrToken: Type<T> | unknown): T | undefined{
13+
let token = null;
14+
if(isConstructor(clsOrToken)){
15+
if(!Reflect.hasMetadata(DI_TOKEN, clsOrToken))
16+
Reflect.defineMetadata(DI_TOKEN, v4(), clsOrToken);
17+
token = Reflect.getMetadata(DI_TOKEN, clsOrToken);
18+
} else {
19+
token = clsOrToken;
20+
}
21+
22+
if(this._instances.has(token))
23+
return this._instances.get(token);
24+
25+
if(isConstructor(clsOrToken)) {
26+
const instance = new clsOrToken() as T;
27+
this.injectProperties(instance, clsOrToken);
28+
this._instances.set(token, instance);
29+
return instance;
30+
}
31+
}
32+
33+
private injectProperties<T>(instance: T, cls: Type<T>){
34+
const propertiesToInject = Reflect.getMetadata(INJECT_METADATA_KEY, cls);
35+
if(!propertiesToInject) return;
36+
37+
for(const [key, token] of Object.entries(propertiesToInject)) {
38+
const value = this.getInstance(token);
39+
Object.defineProperty(instance, key, { value });
40+
}
41+
}
42+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {httpConfigStore, type HttpPath} from "./http.config-store.ts";
2+
import type {Type} from "../types.ts";
3+
4+
export function Route(method: HttpPath['method'], path: string){
5+
return (target: object, property: string, descriptor: TypedPropertyDescriptor<any>) => {
6+
httpConfigStore.paths.add( {
7+
path,
8+
method,
9+
handler: target.constructor as Type<object>,
10+
handlerMethod: property
11+
});
12+
}
13+
}
14+
15+
export function Get(path: string){
16+
return Route('get', path);
17+
}
18+
export function Post(path: string){
19+
return Route('post', path);
20+
}
21+
export function Patch(path: string){
22+
return Route('patch', path);
23+
}
24+
export function Put(path: string){
25+
return Route('put', path);
26+
}

0 commit comments

Comments
 (0)