Skip to content

Commit

Permalink
JavaScript suppport added for project
Browse files Browse the repository at this point in the history
  • Loading branch information
a4arpon committed Nov 13, 2024
1 parent 5d45b34 commit d3ce0c8
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 89 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

### If You Want To Ship Fast, You Have To Build Faster.

** But this framework is more faster than your crush rejects your proposal.**
**But this framework is more faster than your crush rejects your proposal.**

Welcome to **Hot Shot**, a meta-framework built on top of
[Hono](https://honojs.dev/), inspired by the best features of AdonisJS and
Expand Down Expand Up @@ -42,7 +42,7 @@ codebase modular and maintainable.
Copy the starter kit to your project directory and start coding.

```bash
npx jsr add @a4arpon/hotshot-starter-kit
git clone https://github.com/a4arpon/hot-shot-kit.git && cd hot-shot-kit.git && rm -rf .git && code .
```

I am too lazy to write the documentation for this. So, I recommend you to copy the starter kit to your project directory
Expand Down
47 changes: 4 additions & 43 deletions hotshot.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,10 @@
"registry": "https://github.com/a4arpon/hot-shot/registry.json",
"projectType": "ts",
"contains": {
"mods": [
{
"type": "router",
"name": "auth",
"path": "./src/mods/auth-mod",
"contains": [
"router",
"controller",
"services"
],
"services": [
"auth.services"
]
},
{
"type": "router",
"name": "auth",
"path": "./src/mods/auth-mod",
"contains": [
"router",
"controller",
"services"
],
"services": [
"auth.services"
]
},
{
"type": "router",
"name": "auth",
"path": "./src/mods/auth-mod",
"contains": [
"router",
"controller",
"services"
],
"services": [
"auth.services"
]
}
],
"mods": [],
"cacheDrivers": [],
"queues": [],
"useGuards": []
"useGuards": [],
"openApiSpecs": []
}
}
}
2 changes: 1 addition & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@a4arpon/hotshot",
"version": "0.5.3",
"version": "0.5.4",
"exports": "./src/hot-shot.ts",
"license": "MIT"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@a4arpon/hotshot",
"version": "0.5.3",
"version": "0.5.4",
"module": "./src/hot-shot.ts",
"type": "module",
"repository": "https://github.com/a4arpon/hot-shot.git",
Expand Down
13 changes: 7 additions & 6 deletions src/mod-creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
generateWorkerFile,
nameFixer,
} from "./mods-contents.ts"
import { generateCacheDriverContentJS, generateControllerFileJS, generateMiddlewareFileJS, generateOpenApiSpecContentJS, generateRouterFileJS, generateWorkerFileJS } from "./mods-contents-js.ts"

export interface HotShotConf {
projectName: string
Expand Down Expand Up @@ -56,8 +57,8 @@ export async function generateModule(moduleName: string) {

const fileExtensions = projectType === "ts" ? ".ts" : ".js"

const routerContent = generateRouterFile(moduleName, fileExtensions)
const controllerContent = generateControllerFile(moduleName, fileExtensions)
const routerContent = fileExtensions ==='.ts'? generateRouterFile(moduleName, fileExtensions) : generateRouterFileJS(moduleName, fileExtensions)
const controllerContent = fileExtensions ==='.ts'? generateControllerFile(moduleName, fileExtensions) : generateControllerFileJS(moduleName, fileExtensions)
const servicesContent = generateServicesFile(moduleName)

fs.writeFileSync(
Expand Down Expand Up @@ -253,7 +254,7 @@ export async function generateMiddleware(middlewareName: string) {
const config = JSON.parse(configFileContent)

// Generate Middleware Contents
const middlewareContent = generateMiddlewareFile(middlewareName)
const middlewareContent = config.projectTyp ==='ts'? generateMiddlewareFile(middlewareName) : generateMiddlewareFileJS(middlewareName)

// Create middleware file path
const middlewareFileName = `${middlewareName}.guard${
Expand Down Expand Up @@ -310,7 +311,7 @@ export async function queueWorkerGenerator(workerName: string) {
const config = JSON.parse(configFileContent)

// Generate Worker Contents
const workerContent = generateWorkerFile(workerName)
const workerContent = config.projectType === "ts" ? generateWorkerFile(workerName) : generateWorkerFileJS(workerName)

// Create worker file path
const workerFileName = `${workerName}.worker${
Expand Down Expand Up @@ -364,7 +365,7 @@ export async function generateCacheDriver(cacheDriverName: string) {
const config = JSON.parse(configFileContent)

// Generate Cache Driver Contents
const cacheDriverContent = generateCacheDriverContent(cacheDriverName)
const cacheDriverContent = config.projectType === "ts" ? generateCacheDriverContent(cacheDriverName) : generateCacheDriverContentJS(cacheDriverName)

// Create cache driver file path
const cacheDriverFileName = `${cacheDriverName}.cache${
Expand Down Expand Up @@ -423,7 +424,7 @@ export async function generateOpenApiSpec(specName: string) {
const config = JSON.parse(configFileContent)

// Generate OpenApi Spec Contents
const openApiSpecContent = generateOpenApiSpecContent(specName)
const openApiSpecContent = config.projectType === "ts" ? generateOpenApiSpecContent(specName) : generateOpenApiSpecContentJS(specName)

// Create OpenApi Spec file path
const openApiSpecFileName = `${specName}.openapi${
Expand Down
120 changes: 84 additions & 36 deletions src/mods-contents-js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function nameFixer(moduleName: string, isClassName = true): string {
: fixedName
}

export function generateRouterFile(
export function generateRouterFileJS(
moduleName: string,
_fileExtension: string,
): string {
Expand All @@ -22,12 +22,13 @@ export function generateRouterFile(
const controllerMethodName = nameFixer(moduleName, false)

return `
import type {Hono} from "hono";
import {Hono} from "hono";
import {router, routerContainer, route} from "@a4arpon/hotshot";
import {${controllerClassName}} from "./controller";
export class ${routerClassName}Router {
public readonly routes: Hono
/** @type{Hono} */
routes
constructor() {
this.routes = routerContainer({
Expand Down Expand Up @@ -65,18 +66,26 @@ export function generateControllerFileJS(
const serviceMethodName = nameFixer(moduleName, false)

return `
import type {Context} from "hono";
import {Context} from "hono";
import {ApiResponse} from "@a4arpon/hotshot";
import {${serviceName}} from "./${moduleName}.services";
export class ${controllerClassName} {
/**
* @type {${serviceName}}
*/
#${nameFixer(moduleName, false)}Services
constructor() {
this.#${nameFixer(moduleName, false)}Services = new ${serviceName}()
}
/**
* @param {Context} ctx
* @returns {Promise<ApiResponse>}
*/
${controllerFileName} = async (ctx) => {
return this.${nameFixer(
return this.#${nameFixer(
moduleName,
false,
)}Services.${serviceMethodName}()
Expand All @@ -85,7 +94,7 @@ export class ${controllerClassName} {
`
}

export function generateServicesFile(moduleName: string): string {
export function generateServicesFileJS(moduleName: string): string {
const servicesClassName = `${nameFixer(moduleName, true)}Services`
const serviceMethodName = nameFixer(moduleName, false)

Expand All @@ -100,14 +109,21 @@ export class ${servicesClassName} {
`
}

export function generateMiddlewareFile(middlewareName: string): string {
export function generateMiddlewareFileJS(middlewareName: string): string {
const middlewareClassName = `${nameFixer(middlewareName, true)}Guard`
return `
import { type UseGuard, HTTPStatus } from "@a4arpon/hotshot";
import { UseGuard, HTTPStatus } from "@a4arpon/hotshot";
import {Context, Next} from "hono";
import { HTTPException } from "hono/http-exception"
export class ${middlewareClassName} implements UseGuard {
/** @type {Context, Next} */
/**
* @implements {UseGuard}
*/
export class ${middlewareClassName} {
/**
* @param {Context} ctx
* @param {Next} next
*/
async use(ctx, next) {
if (ctx.req.path === "/${middlewareName.toLowerCase()}-guard") {
throw new HTTPException(HTTPStatus.BadRequest, {
Expand All @@ -121,11 +137,11 @@ export class ${middlewareClassName} implements UseGuard {
}`
}

export function generateWorkerFile(workerName: string): string {
export function generateWorkerFileJS(workerName: string): string {
const workerClassName = `${nameFixer(workerName, true)}Queue`

return `
import { type Job, Worker } from "bullmq"
import { Worker } from "bullmq"
import { ${nameFixer(workerName, false)}Queue, redis } from "#libs/conn"
/*
Expand All @@ -139,7 +155,11 @@ import { ${nameFixer(workerName, false)}Queue, redis } from "#libs/conn"
*/
export class ${workerClassName}Worker {
public readonly worker
/**
* @type {Worker}
*/
worker
constructor() {
this.worker = new Worker(
Expand Down Expand Up @@ -196,8 +216,16 @@ export function generateCacheDriverContentJS(cacheDriverName: string): string {
import { cacheNameGen, cacheResponse } from "#libs/ioredis-json"
export class ${cacheDriverClassName} {
public readonly cachePartition = "${nameFixer(cacheDriverName, false)}-cache"
/**
* @type {string}
*/
cachePartition = "${nameFixer(cacheDriverName, false)}-cache"
/**
* @param {string} key
* @param {any} payload
* @returns {Promise<any>}
*/
async create(key, payload) {
return cacheResponse(
cacheNameGen(this.cachePartition, key),
Expand All @@ -206,6 +234,10 @@ export class ${cacheDriverClassName} {
)
}
/**
* @param {string} key
* @returns {Promise<any>}
*/
async get(key) {
return cacheResponse(
cacheNameGen(this.cachePartition, key),
Expand All @@ -214,6 +246,11 @@ export class ${cacheDriverClassName} {
)
}
/**
* @param {string} key
* @param {any} payload
* @returns {Promise<any>}
*/
async update(key, payload) {
return cacheResponse(
cacheNameGen(this.cachePartition, key),
Expand All @@ -222,6 +259,10 @@ export class ${cacheDriverClassName} {
)
}
/**
* @param {string} key
* @returns {Promise<any>}
*/
async delete(key) {
return cacheResponse(
cacheNameGen(this.cachePartition, key),
Expand All @@ -233,35 +274,22 @@ export class ${cacheDriverClassName} {
`
}

export function generateOpenApiSpecContent(specName: string): string {
export function generateOpenApiSpecContentJS(specName: string): string {
const openAPISpecClassName = `${nameFixer(specName, true)}OpenApiSpecs`

return `
import type { ApiSpecs, UseOpenApi } from "#libs/open-api"
import { ApiSpecs, UseOpenApi } from "#libs/open-api"
import { z } from "zod"
/*
* ------------------------------------------------------------------------
* Open API Specs
*
* Some Key Points -
* 1. To use path params, you need to use the path param syntax in the path
* and the path param name in the pathParams array.
* Example: path: "/author/{authorSlug}", pathParams: ["authorSlug"]
* Second brackets {} are used to define the path param syntax.
*
* 2. To define a request body, you need to define it as a ZodSchema and
* pass it to the requestBody property.
* Example: requestBody: z.object({ title: z.string() })
*
* Tips: In this project we are using Drizzle-ORM, so we can easilty inherit
* the ZodSchema from the drizzle-orm.
* Doc Link: https://orm.drizzle.team/docs/zod
* ------------------------------------------------------------------------
/**
* @implements {UseOpenApi}
*/
export class ${openAPISpecClassName} {
export class ${openAPISpecClassName} implements UseOpenApi {
public readonly specs: ApiSpecs[]
/**
* @type {ApiSpecs[]}
*/
specs
constructor() {
this.specs = [
Expand Down Expand Up @@ -316,5 +344,25 @@ export function generateOpenApiSpecContent(specName: string): string {
]
}
}
/*
* ------------------------------------------------------------------------
* Open API Specs
*
* Some Key Points -
* 1. To use path params, you need to use the path param syntax in the path
* and the path param name in the pathParams array.
* Example: path: "/author/{authorSlug}", pathParams: ["authorSlug"]
* Second brackets {} are used to define the path param syntax.
*
* 2. To define a request body, you need to define it as a ZodSchema and
* pass it to the requestBody property.
* Example: requestBody: z.object({ title: z.string() })
*
* Tips: In this project we are using Drizzle-ORM, so we can easilty inherit
* the ZodSchema from the drizzle-orm.
* Doc Link: https://orm.drizzle.team/docs/zod
* ------------------------------------------------------------------------
*/
`
}

0 comments on commit d3ce0c8

Please sign in to comment.