Browse Source

fixed 部署

theme
npmrun 2 years ago
parent
commit
1df1edafd6
  1. 2
      Dockerfile
  2. 6
      package.json
  3. 2221
      pnpm-lock.yaml
  4. 18
      readme.md
  5. 4
      route.txt
  6. 190
      source/plugins/router-plugin/index.ts
  7. 40
      source/plugins/router-plugin/util/decorators.ts
  8. 81
      source/plugins/router-plugin/util/index.ts
  9. 2
      source/run.ts
  10. 3
      tsconfig.json

2
Dockerfile

@ -16,6 +16,6 @@ COPY pnpm-lock.yaml ./
RUN pnpm install
EXPOSE 3000
EXPOSE 3388
CMD [ "pnpm", "start" ]

6
package.json

@ -52,7 +52,6 @@
"@hapi/code": "^9.0.1",
"@hapi/lab": "^25.0.1",
"@hapi/vision": "^6.1.0",
"@noderun/hapi-router": "workspace:*",
"@types/fs-extra": "^9.0.13",
"@types/hapi__cookie": "^10.1.4",
"@types/hapi__crumb": "^7.3.3",
@ -71,6 +70,11 @@
"typescript": "^4.3.2"
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"openapi-types"
]
},
"patchedDependencies": {
"hapi-sequelizejs@4.5.0": "patches/hapi-sequelizejs@4.5.0.patch"
}

2221
pnpm-lock.yaml

File diff suppressed because it is too large

18
readme.md

@ -23,4 +23,20 @@ https://hapi.dev/module/catbox/api/?v=12.1.0
https://juejin.cn/post/7067093432737398792
https://juejin.cn/post/7067093432737398792
https://blog.csdn.net/qq_31155349/article/details/109013323
https://blog.csdn.net/tiger1334/article/details/93468736
docker build -t hapi-website -f ./Dockerfile ./
docker run -itd --name website -p 8899:3388 hapi-website /bin/bash
docker exec -it 容器ID /bin/bash
## 清除
docker stop 容器ID
docker container prune
docker image rm 镜像名
docker image ls -a
docker container ls -a

4
route.txt

@ -1,6 +1,6 @@
D:\1XYX\pro\hapi-demo\source\route\htmx对应路径:
/home/topuser/Code/@project/hapi-demo/dist/route/htmx对应路径:
不需权限 : GET /htmx/path/{path*}
D:\1XYX\pro\hapi-demo\source\route\views对应路径:
/home/topuser/Code/@project/hapi-demo/dist/route/views对应路径:
不需权限(提供无需验证): GET /404
不需权限 : GET /css
不需权限(提供无需验证): GET /

190
source/plugins/router-plugin/index.ts

@ -0,0 +1,190 @@
// @ts-nocheck
import { walkDir, removeIndex, isIndexEnd } from "./util"
import * as Joi from "joi"
const path = require("path")
const fs = require("fs")
class routePlugin {
public name: string = "routePlugin"
public version: string = "0.0.1"
public register(server: any, opts: any) {
const sourceDir = opts.sourceDir
const type = opts.type || "jwt"
const auth = opts.auth || []
let array = []
for (let i = 0; i < sourceDir.length; i++) {
const dir = sourceDir[i]
console.log(dir)
array.push(dir.dir + "对应路径:")
array = array.concat(this.registerRoute(server, dir.dir, dir.prefix || "", auth, type))
}
fs.writeFileSync(path.resolve(process.cwd(), "route.txt"), array.join("\n"), {
encoding: "utf-8",
})
}
registerRoute(server, sourceDir, prefix, auth, type) {
const files = walkDir(sourceDir)
const routes = []
files.forEach(file => {
let filename = file.relativeFileNoExt
let array = filename.split(path.sep).slice(1)
let fileNoExt = removeIndex("/" + array.join("/"))
const moduleName = path.resolve(sourceDir, filename)
const obj = require(moduleName)
if (obj.default) {
const func = new (obj.default || obj)()
const prototype = Object.getPrototypeOf(func)
const keys = Reflect.ownKeys(prototype)
for (const key of keys) {
if (key !== "constructor") {
let ff = func[key]
let handler: () => void = undefined
// 默认方法
const method = ff.$method || "GET"
// 路由收集规则
let route = ""
if (ff.$route) {
if (isIndexEnd(fileNoExt)) {
route = ff.$route
} else {
route = fileNoExt + ff.$route
}
} else {
if (isIndexEnd(fileNoExt)) {
route = fileNoExt + key.toString()
} else {
route = fileNoExt + "/" + key.toString()
}
}
route = removeIndex(route)
route = prefix ? route[0] + prefix + "/" + route.slice(1) : route
// 配置规则
const options = ff.$options ? ff.$options : {}
if (!options.auth) {
if (ff.$auth == undefined) {
if (auth && auth.length && auth.filter(v => route.startsWith(v)).length) {
options.auth = type
} else {
options.auth = false
}
} else if (ff.$auth) {
options.auth =
typeof ff.$auth === "boolean"
? type
: {
strategy: type,
mode: ff.$auth,
}
} else {
options.auth = false
}
}
if (!options.validate) {
let validateObj = ff.$validate || {}
if (options.auth && type === "jwt") {
if (validateObj.headers) {
validateObj.headers = validateObj.headers.keys({
Authorization: Joi.string(),
})
} else {
validateObj.headers = Joi.object({
headers: Joi.object({
Authorization: Joi.string(),
}).unknown(), // 注意加上这个
})
}
}
if (validateObj && !!Object.keys(validateObj).length) {
const failReason = validateObj.failReason
delete validateObj.failReason
if (validateObj.failAction === "log") {
if (!options.log) options.log = {}
options.log.collect = true
let errto = validateObj.$errto
handler = async function (...argus) {
const request = argus[0]
const h = argus[1]
if (request.logs && !!request.logs.length && errto) {
// request.yar.flash('error', request.logs.map((v: any)=>v.error.message));
request.yar.flash("error", failReason || request.logs.map((v: any)=>v.error.message))
return h.redirect(errto)
}
return await ff.call(this, ...argus)
}
}
if (validateObj.failAction === "function") {
let errto = validateObj.$errto
validateObj.failAction = async function (request, h, err) {
if (err.details) {
request.$joi_error = err.details.map(v => v.message)
}
return h.continue
}
handler = async function (...argus) {
const request = argus[0]
const h = argus[1]
if (request.$joi_error) {
loggerSite.debug("传输参数错误: ", request.$joi_error)
request.yar.flash("error", failReason || request.$joi_error)
delete request.$joi_error
return h.redirect(errto)
}
return await ff.call(this, ...argus)
}
}
options.validate = validateObj
}
}
// && route.startsWith("/api")
if (ff.$swagger) {
options.description = ff.$swagger[0]
options.notes = ff.$swagger[1]
options.tags = ff.$swagger[2]
}
let str = route
if (
(typeof options.auth === "string" && options.auth) ||
(typeof options.auth === "object" && options.auth.mode === "required")
) {
str = " 需要权限 : " + " " + full(method) + " " + str
} else if (typeof options.auth === "object" && options.auth.mode === "optional") {
str = " 不需权限(提供即需验证): " + " " + full(method) + " " + str
} else if (typeof options.auth === "object" && options.auth.mode === "try") {
str = " 不需权限(提供无需验证): " + " " + full(method) + " " + str
} else {
str = " 不需权限 : " + " " + full(method) + " " + str
}
routes.push(str)
if (options.validate && options.validate.$errto) {
delete options.validate.$errto
}
if (!handler) {
handler = ff
}
server.route({
method: method,
path: route,
handler: handler,
options: options,
})
}
}
}
})
return routes
}
}
function full(str: string, length = 10) {
let len = str.length
let need = length - len
if (need <= 0) return str
return str + [...Array(need)].map((v, i) => " ").join("")
}
const plugin = new routePlugin()
export { plugin }
export * from "./util/decorators"

40
source/plugins/router-plugin/util/decorators.ts

@ -0,0 +1,40 @@
// @ts-nocheck
/**
*
* @param opts
*/
type TMethod = "GET" | "POST" | "PUT" | "DELETE"
export function method(opts?: TMethod | Array<TMethod>) {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
target[propertyKey].$method = opts
}
}
export function route(route?: string) {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
target[propertyKey].$route = route
}
}
export function config(options: Object) {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
target[propertyKey].$options = options
}
}
export function auth(isAuth: boolean | "try" | "required" | "optional" = true) {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
target[propertyKey].$auth = isAuth
}
}
export function validate(validate: Object) {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
target[propertyKey].$validate = validate
}
}
export function swagger(desc, notes, tags) {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
target[propertyKey].$swagger = [desc, notes, tags]
}
}

81
source/plugins/router-plugin/util/index.ts

@ -0,0 +1,81 @@
// @ts-nocheck
const path = require("path")
const fs = require("fs")
export function removeIndex(ss: any) {
const remove = (str: any) => {
if (str.endsWith("/index")) {
return str.slice(0, -6)
}
if (str.endsWith("index")) {
return str.slice(0, -5)
}
return str ? str : "/"
}
let r = true
let rr = ss
while (r) {
if (rr.endsWith("/index")) {
rr = remove(rr)
} else {
r = false
}
}
return rr ? rr : "/"
}
export function isIndexEnd(str: any) {
return str.length == 1 && str.endsWith("/")
}
export function walkDir(
filePath: any,
exclude = ["node_modules", "^_", ".git", ".idea", ".gitignore", "client", ".txt$", ".test.js$", ".test.ts$"],
) {
let files: any[] = []
function Data(opts: any) {
this.relativeDir = opts.relativeDir
this.relativeFile = opts.relativeFile
this.filename = opts.filename
this.file = opts.file
this.absoluteFile = opts.absoluteFile
this.relativeFileNoExt = opts.relativeFileNoExt
this.absoluteDir = opts.absoluteDir
}
function readDir(filePath, dirname = ".") {
let res = fs.readdirSync(filePath)
res.forEach(filename => {
const filepath = path.resolve(filePath, filename)
const stat = fs.statSync(filepath)
const name = filepath.split(path.sep).slice(-1)[0]
if (typeof exclude === "string" && new RegExp(exclude).test(name)) {
return
}
if (Array.isArray(exclude)) {
for (let i = 0; i < exclude.length; i++) {
const excludeItem = exclude[i]
if (new RegExp(excludeItem).test(name)) {
return
}
}
}
if (!stat.isFile()) {
readDir(filepath, dirname + path.sep + name)
} else {
const data = new Data({
relativeDir: dirname,
relativeFile: dirname + path.sep + path.parse(filepath).base,
relativeFileNoExt: dirname + path.sep + path.parse(filepath).name,
file: path.parse(filepath).base,
filename: path.parse(filepath).name,
absoluteFile: filepath,
absoluteDir: path.parse(filepath).dir,
})
files.push(data)
}
})
}
readDir(filePath)
return files
}

2
source/run.ts

@ -15,7 +15,7 @@ const pugPluginAlias = require("pug-alias")
const run = async (): Promise<Server> => {
const server = Hapi.server({
port: 3388,
host: "localhost",
host: "0.0.0.0",
})
await server.register([
{

3
tsconfig.json

@ -13,7 +13,8 @@
"esModuleInterop": true, // esModuleInterop使import d from 'cjs'commonjs
"baseUrl": ".",
"paths": {
"@noderun/hapi-router": ["packages/hapi-router/src/index.ts"],
// "@noderun/hapi-router": ["packages/hapi-router/src/index.ts"],
"@noderun/hapi-router": ["source/plugins/router-plugin/index.ts"],
"@/*": ["source/*"],
"#/*": ["types/*"]
}

Loading…
Cancel
Save