@hono-di/client 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +0 -2
- package/dist/index.js +0 -2
- package/package.json +1 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generator.ts"],"names":["Project"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Project, ClassDeclaration, MethodDeclaration, Decorator } from 'ts-morph';\nimport * as path from 'path';\n\nexport interface GeneratorOptions {\n tsConfigFilePath: string;\n output?: string;\n}\n\nexport class TypeGenerator {\n constructor(private readonly options: GeneratorOptions) { }\n\n async generate(): Promise<string> {\n const project = new Project({\n tsConfigFilePath: this.options.tsConfigFilePath,\n });\n\n const controllers = this.findControllers(project);\n const routes = this.extractRoutes(controllers, project);\n\n return this.buildTypeDefinition(routes);\n }\n\n private findControllers(project: Project): ClassDeclaration[] {\n const controllers: ClassDeclaration[] = [];\n const sourceFiles = project.getSourceFiles();\n\n for (const sourceFile of sourceFiles) {\n const classes = sourceFile.getClasses();\n for (const cls of classes) {\n if (this.hasDecorator(cls, 'Controller')) {\n controllers.push(cls);\n }\n }\n }\n return controllers;\n }\n\n private extractRoutes(controllers: ClassDeclaration[], project: Project) {\n const routes: any[] = [];\n\n for (const controller of controllers) {\n const controllerPrefix = this.getDecoratorArgument(controller, 'Controller') || '';\n const methods = controller.getMethods();\n\n for (const method of methods) {\n const methodDecorator = this.getMethodDecorator(method);\n if (methodDecorator) {\n const methodPath = this.getDecoratorArgument(method, methodDecorator.getName()) || '/';\n const httpMethod = methodDecorator.getName().toLowerCase(); // Get, Post -> get, post\n const returnType = method.getReturnType().getText();\n\n // Normalize path\n const fullPath = this.normalizePath(controllerPrefix, methodPath);\n\n // Collect return type\n this.collectType(returnType, project);\n\n routes.push({\n path: fullPath,\n method: httpMethod,\n returnType,\n methodName: method.getName(),\n parameters: method.getParameters().map(p => {\n const typeText = p.getType().getText();\n this.collectType(typeText, project);\n return {\n name: p.getName(),\n type: typeText,\n decorators: p.getDecorators().map(d => ({\n name: d.getName(),\n arguments: d.getArguments().map(arg => arg.getText().replace(/^['\"]|['\"]$/g, ''))\n }))\n };\n })\n });\n }\n }\n }\n return routes;\n }\n\n private extraTypes = new Map<string, string>();\n\n private collectType(typeText: string, project: Project) {\n // Simple heuristic: if it starts with uppercase and is not a primitive\n const primitives = ['string', 'number', 'boolean', 'any', 'void', 'null', 'undefined', 'Date'];\n const isArray = typeText.endsWith('[]');\n const baseType = isArray ? typeText.slice(0, -2) : typeText;\n\n if (primitives.includes(baseType) || baseType.startsWith('{') || baseType.includes('<')) {\n return;\n }\n\n if (this.extraTypes.has(baseType)) {\n return;\n }\n\n // Find the class or interface in the project\n for (const sourceFile of project.getSourceFiles()) {\n const cls = sourceFile.getClass(baseType);\n if (cls) {\n const properties = cls.getProperties().map(p => {\n return `${p.getName()}: ${p.getType().getText()};`;\n });\n this.extraTypes.set(baseType, `export interface ${baseType} {\\n ${properties.join('\\n ')}\\n}`);\n return;\n }\n\n const intf = sourceFile.getInterface(baseType);\n if (intf) {\n const properties = intf.getProperties().map(p => {\n return `${p.getName()}: ${p.getType().getText()};`;\n });\n this.extraTypes.set(baseType, `export interface ${baseType} {\\n ${properties.join('\\n ')}\\n}`);\n return;\n }\n }\n }\n\n private buildTypeDefinition(routes: any[]): string {\n let typeDef = `import { Hono } from 'hono';\\n`;\n typeDef += `import type { InferRequestType, InferResponseType } from 'hono/client';\\n\\n`;\n\n // Add extra types\n for (const [name, def] of this.extraTypes) {\n typeDef += `${def}\\n\\n`;\n }\n\n typeDef += `export type AppType = Hono<any, {\\n`;\n\n // Group routes by path\n const routesByPath: Record<string, any[]> = {};\n for (const route of routes) {\n if (!routesByPath[route.path]) {\n routesByPath[route.path] = [];\n }\n routesByPath[route.path].push(route);\n }\n\n for (const [path, pathRoutes] of Object.entries(routesByPath)) {\n typeDef += ` '${path}': {\\n`;\n for (const route of pathRoutes) {\n let inputType = '';\n const inputFields: string[] = [];\n\n // Handle Body\n const bodyParam = route.parameters.find((p: any) => p.decorators.some((d: any) => d.name === 'Body'));\n if (bodyParam) {\n inputFields.push(`json: ${bodyParam.type}`);\n }\n\n // Handle Query\n const queryParam = route.parameters.find((p: any) => p.decorators.some((d: any) => d.name === 'Query'));\n if (queryParam) {\n inputFields.push(`query: ${queryParam.type}`);\n }\n\n // Handle Param\n const paramParams = route.parameters.filter((p: any) => p.decorators.some((d: any) => d.name === 'Param'));\n if (paramParams.length > 0) {\n const paramFields = paramParams.map((p: any) => {\n const decorator = p.decorators.find((d: any) => d.name === 'Param');\n const paramName = decorator.arguments[0] || p.name;\n return `${paramName}: ${p.type}`;\n });\n inputFields.push(`param: { ${paramFields.join('; ')} }`);\n }\n\n inputType = `{ ${inputFields.join(', ')} }`;\n\n typeDef += ` $${route.method}: {\\n`;\n typeDef += ` input: ${inputType},\\n`;\n typeDef += ` output: { json: ${route.returnType} },\\n`;\n typeDef += ` outputFormat: 'json',\\n`;\n typeDef += ` status: 200\\n`;\n typeDef += ` },\\n`;\n }\n typeDef += ` },\\n`;\n }\n\n typeDef += `}>;\\n`;\n return typeDef;\n }\n\n private hasDecorator(node: ClassDeclaration | MethodDeclaration, name: string): boolean {\n return node.getDecorators().some(d => d.getName() === name);\n }\n\n private getMethodDecorator(method: MethodDeclaration): Decorator | undefined {\n const methods = ['Get', 'Post', 'Put', 'Delete', 'Patch'];\n return method.getDecorators().find(d => methods.includes(d.getName()));\n }\n\n private getDecoratorArgument(node: ClassDeclaration | MethodDeclaration, name: string): string | undefined {\n const decorator = node.getDecorator(name);\n if (!decorator) return undefined;\n const args = decorator.getArguments();\n if (args.length > 0) {\n const text = args[0].getText();\n // Remove quotes\n return text.replace(/^['\"]|['\"]$/g, '');\n }\n return undefined;\n }\n\n private normalizePath(prefix: string, path: string): string {\n const cleanPrefix = prefix ? prefix.replace(/^\\/+/, '').replace(/\\/+$/, '') : '';\n const cleanPath = path ? path.replace(/^\\/+/, '').replace(/\\/+$/, '') : '';\n let result = '';\n if (cleanPrefix) result += `/${cleanPrefix}`;\n if (cleanPath) result += `/${cleanPath}`;\n return result || '/';\n }\n}\n"]}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generator.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { Project, ClassDeclaration, MethodDeclaration, Decorator } from 'ts-morph';\nimport * as path from 'path';\n\nexport interface GeneratorOptions {\n tsConfigFilePath: string;\n output?: string;\n}\n\nexport class TypeGenerator {\n constructor(private readonly options: GeneratorOptions) { }\n\n async generate(): Promise<string> {\n const project = new Project({\n tsConfigFilePath: this.options.tsConfigFilePath,\n });\n\n const controllers = this.findControllers(project);\n const routes = this.extractRoutes(controllers, project);\n\n return this.buildTypeDefinition(routes);\n }\n\n private findControllers(project: Project): ClassDeclaration[] {\n const controllers: ClassDeclaration[] = [];\n const sourceFiles = project.getSourceFiles();\n\n for (const sourceFile of sourceFiles) {\n const classes = sourceFile.getClasses();\n for (const cls of classes) {\n if (this.hasDecorator(cls, 'Controller')) {\n controllers.push(cls);\n }\n }\n }\n return controllers;\n }\n\n private extractRoutes(controllers: ClassDeclaration[], project: Project) {\n const routes: any[] = [];\n\n for (const controller of controllers) {\n const controllerPrefix = this.getDecoratorArgument(controller, 'Controller') || '';\n const methods = controller.getMethods();\n\n for (const method of methods) {\n const methodDecorator = this.getMethodDecorator(method);\n if (methodDecorator) {\n const methodPath = this.getDecoratorArgument(method, methodDecorator.getName()) || '/';\n const httpMethod = methodDecorator.getName().toLowerCase(); // Get, Post -> get, post\n const returnType = method.getReturnType().getText();\n\n // Normalize path\n const fullPath = this.normalizePath(controllerPrefix, methodPath);\n\n // Collect return type\n this.collectType(returnType, project);\n\n routes.push({\n path: fullPath,\n method: httpMethod,\n returnType,\n methodName: method.getName(),\n parameters: method.getParameters().map(p => {\n const typeText = p.getType().getText();\n this.collectType(typeText, project);\n return {\n name: p.getName(),\n type: typeText,\n decorators: p.getDecorators().map(d => ({\n name: d.getName(),\n arguments: d.getArguments().map(arg => arg.getText().replace(/^['\"]|['\"]$/g, ''))\n }))\n };\n })\n });\n }\n }\n }\n return routes;\n }\n\n private extraTypes = new Map<string, string>();\n\n private collectType(typeText: string, project: Project) {\n // Simple heuristic: if it starts with uppercase and is not a primitive\n const primitives = ['string', 'number', 'boolean', 'any', 'void', 'null', 'undefined', 'Date'];\n const isArray = typeText.endsWith('[]');\n const baseType = isArray ? typeText.slice(0, -2) : typeText;\n\n if (primitives.includes(baseType) || baseType.startsWith('{') || baseType.includes('<')) {\n return;\n }\n\n if (this.extraTypes.has(baseType)) {\n return;\n }\n\n // Find the class or interface in the project\n for (const sourceFile of project.getSourceFiles()) {\n const cls = sourceFile.getClass(baseType);\n if (cls) {\n const properties = cls.getProperties().map(p => {\n return `${p.getName()}: ${p.getType().getText()};`;\n });\n this.extraTypes.set(baseType, `export interface ${baseType} {\\n ${properties.join('\\n ')}\\n}`);\n return;\n }\n\n const intf = sourceFile.getInterface(baseType);\n if (intf) {\n const properties = intf.getProperties().map(p => {\n return `${p.getName()}: ${p.getType().getText()};`;\n });\n this.extraTypes.set(baseType, `export interface ${baseType} {\\n ${properties.join('\\n ')}\\n}`);\n return;\n }\n }\n }\n\n private buildTypeDefinition(routes: any[]): string {\n let typeDef = `import { Hono } from 'hono';\\n`;\n typeDef += `import type { InferRequestType, InferResponseType } from 'hono/client';\\n\\n`;\n\n // Add extra types\n for (const [name, def] of this.extraTypes) {\n typeDef += `${def}\\n\\n`;\n }\n\n typeDef += `export type AppType = Hono<any, {\\n`;\n\n // Group routes by path\n const routesByPath: Record<string, any[]> = {};\n for (const route of routes) {\n if (!routesByPath[route.path]) {\n routesByPath[route.path] = [];\n }\n routesByPath[route.path].push(route);\n }\n\n for (const [path, pathRoutes] of Object.entries(routesByPath)) {\n typeDef += ` '${path}': {\\n`;\n for (const route of pathRoutes) {\n let inputType = '';\n const inputFields: string[] = [];\n\n // Handle Body\n const bodyParam = route.parameters.find((p: any) => p.decorators.some((d: any) => d.name === 'Body'));\n if (bodyParam) {\n inputFields.push(`json: ${bodyParam.type}`);\n }\n\n // Handle Query\n const queryParam = route.parameters.find((p: any) => p.decorators.some((d: any) => d.name === 'Query'));\n if (queryParam) {\n inputFields.push(`query: ${queryParam.type}`);\n }\n\n // Handle Param\n const paramParams = route.parameters.filter((p: any) => p.decorators.some((d: any) => d.name === 'Param'));\n if (paramParams.length > 0) {\n const paramFields = paramParams.map((p: any) => {\n const decorator = p.decorators.find((d: any) => d.name === 'Param');\n const paramName = decorator.arguments[0] || p.name;\n return `${paramName}: ${p.type}`;\n });\n inputFields.push(`param: { ${paramFields.join('; ')} }`);\n }\n\n inputType = `{ ${inputFields.join(', ')} }`;\n\n typeDef += ` $${route.method}: {\\n`;\n typeDef += ` input: ${inputType},\\n`;\n typeDef += ` output: { json: ${route.returnType} },\\n`;\n typeDef += ` outputFormat: 'json',\\n`;\n typeDef += ` status: 200\\n`;\n typeDef += ` },\\n`;\n }\n typeDef += ` },\\n`;\n }\n\n typeDef += `}>;\\n`;\n return typeDef;\n }\n\n private hasDecorator(node: ClassDeclaration | MethodDeclaration, name: string): boolean {\n return node.getDecorators().some(d => d.getName() === name);\n }\n\n private getMethodDecorator(method: MethodDeclaration): Decorator | undefined {\n const methods = ['Get', 'Post', 'Put', 'Delete', 'Patch'];\n return method.getDecorators().find(d => methods.includes(d.getName()));\n }\n\n private getDecoratorArgument(node: ClassDeclaration | MethodDeclaration, name: string): string | undefined {\n const decorator = node.getDecorator(name);\n if (!decorator) return undefined;\n const args = decorator.getArguments();\n if (args.length > 0) {\n const text = args[0].getText();\n // Remove quotes\n return text.replace(/^['\"]|['\"]$/g, '');\n }\n return undefined;\n }\n\n private normalizePath(prefix: string, path: string): string {\n const cleanPrefix = prefix ? prefix.replace(/^\\/+/, '').replace(/\\/+$/, '') : '';\n const cleanPath = path ? path.replace(/^\\/+/, '').replace(/\\/+$/, '') : '';\n let result = '';\n if (cleanPrefix) result += `/${cleanPrefix}`;\n if (cleanPath) result += `/${cleanPath}`;\n return result || '/';\n }\n}\n"]}
|