waibu 1.0.10 → 1.0.12
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/bajo/config.json +4 -0
- package/bajo/intl/en-US.json +2 -1
- package/bajo/intl/id.json +2 -1
- package/bajo/method/send-mail.js +19 -0
- package/bajoTemplate/layout/email.html +17 -0
- package/bajoTemplate/layout/email.id.html +18 -0
- package/lib/build-locals.js +46 -0
- package/lib/webapp-scope/handle-compress.js +4 -2
- package/lib/webapp-scope/handle-cors.js +4 -2
- package/lib/webapp-scope/handle-helmet.js +4 -2
- package/lib/webapp-scope/handle-multipart-body.js +3 -2
- package/lib/webapp-scope/handle-rate-limit.js +4 -2
- package/package.json +1 -1
package/bajo/config.json
CHANGED
package/bajo/intl/en-US.json
CHANGED
|
@@ -10,5 +10,6 @@
|
|
|
10
10
|
"routeDisabled%s%s": "Route %s (%s) is disabled",
|
|
11
11
|
"rerouted%s%s": "Rerouted %s -> %s",
|
|
12
12
|
"bootSubApp%s": "Boot sub app: %s",
|
|
13
|
-
"routeNotFound%s%s": "Route '%s (%s)' not found"
|
|
13
|
+
"routeNotFound%s%s": "Route '%s (%s)' not found",
|
|
14
|
+
"middlewareDisabled%s": "Middleware '%s' is disabled"
|
|
14
15
|
}
|
package/bajo/intl/id.json
CHANGED
|
@@ -10,5 +10,6 @@
|
|
|
10
10
|
"routeDisabled%s%s": "Jalur %s (%s) dimatikan",
|
|
11
11
|
"rerouted%s%s": "Jalur dipindahkan %s -> %s",
|
|
12
12
|
"bootSubApp%s": "Boot sub app: %s",
|
|
13
|
-
"routeNotFound%s%s": "Jalur '%s (%s)' tidak ditemukan"
|
|
13
|
+
"routeNotFound%s%s": "Jalur '%s (%s)' tidak ditemukan",
|
|
14
|
+
"middlewareDisabled%s": "Middleware '%s' dimatikan"
|
|
14
15
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import buildLocals from '../../lib/build-locals.js'
|
|
2
|
+
|
|
3
|
+
async function sendMail (tpl, { to, cc, bcc, from, subject, data = {}, conn, options = {} }) {
|
|
4
|
+
if (!this.app.masohiMail) return
|
|
5
|
+
const { get, isString } = this.app.bajo.lib._
|
|
6
|
+
const { generateId } = this.app.bajo
|
|
7
|
+
const { render } = this.app.bajoTemplate
|
|
8
|
+
if (isString(tpl)) tpl = [tpl]
|
|
9
|
+
const locals = await buildLocals.call(this, { tpl, params: data, opts: options })
|
|
10
|
+
const opts = {
|
|
11
|
+
lang: get(options, 'req.lang'),
|
|
12
|
+
groupId: get(options, 'req.id', generateId())
|
|
13
|
+
}
|
|
14
|
+
const message = await render(tpl[0], locals, opts)
|
|
15
|
+
if (tpl[1]) opts.messageText = await render(tpl[1], locals, opts)
|
|
16
|
+
await this.app.masohi.send({ to, cc, bcc, from, subject, message, conn, options: opts })
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default sendMail
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<head lang="<%= _meta.lang %>">
|
|
3
|
+
<meta charset="UTF-8">
|
|
4
|
+
<title><%= page.fullTitle %></title>
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
</style>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<% if (arguments[0].firstName && arguments[0].lastName) { %>
|
|
10
|
+
<p>Dear <%= firstName %> <%= lastName %>,</p>
|
|
11
|
+
<% } %>
|
|
12
|
+
<!-- body -->
|
|
13
|
+
<p>Sincerely,</p>
|
|
14
|
+
|
|
15
|
+
<p><%= _meta.site.title %></p>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="<%= _meta.lang %>">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title><%= page.fullTitle %></title>
|
|
6
|
+
<style type="text/css">
|
|
7
|
+
</style>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<% if (arguments[0].firstName && arguments[0].lastName) { %>
|
|
11
|
+
<p>Yth <%= firstName %> <%= lastName %>,</p>
|
|
12
|
+
<% } %>
|
|
13
|
+
<!-- body -->
|
|
14
|
+
<p>Hormat kami,</p>
|
|
15
|
+
|
|
16
|
+
<p><%= _meta.site.title %></p>
|
|
17
|
+
</body>
|
|
18
|
+
</html>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function buildHomesMenu () {
|
|
2
|
+
const { get, find, orderBy } = this.app.bajo.lib._
|
|
3
|
+
const routes = []
|
|
4
|
+
for (const ns of this.app.bajo.pluginNames) {
|
|
5
|
+
const href = get(this, `app.${ns}.config.waibuMpa.home`)
|
|
6
|
+
if (!href) continue
|
|
7
|
+
const item = { href, ns, title: get(this, `app.${ns}.config.waibu.title`, this.app[ns].title) }
|
|
8
|
+
if (!find(routes, { href })) routes.push(item)
|
|
9
|
+
}
|
|
10
|
+
return orderBy(routes, ['title'])
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function buildLocals ({ tpl, params = {}, opts = {} } = {}) {
|
|
14
|
+
const { runHook } = this.app.bajo
|
|
15
|
+
const { set, merge, pick, get, isEmpty, find } = this.app.bajo.lib._
|
|
16
|
+
const { req, reply } = opts
|
|
17
|
+
|
|
18
|
+
const appTitle = this.app.waibuMpa ? this.app.waibuMpa.getAppTitle(req.ns) : undefined
|
|
19
|
+
params.page = merge(params.page ?? {}, { ns: req.ns, appTitle })
|
|
20
|
+
set(params, 'menu.homes', buildHomesMenu.call(this))
|
|
21
|
+
|
|
22
|
+
const { site, user, lang, darkMode } = req
|
|
23
|
+
const theme = pick(find(this.themes, { name: req.theme }) ?? {}, ['name', 'framework'])
|
|
24
|
+
const iconset = pick(find(this.iconsets, { name: req.iconset }) ?? {}, ['name'])
|
|
25
|
+
const routeOpts = get(req, 'routeOptions.config', {})
|
|
26
|
+
const _meta = { theme, iconset, site, user, lang, darkMode, routeOpts }
|
|
27
|
+
_meta.site = _meta.site ?? {}
|
|
28
|
+
merge(_meta, pick(req, ['url', 'params', 'query']))
|
|
29
|
+
_meta.env = this.app.bajo.config.env
|
|
30
|
+
_meta.url = _meta.url.split('?')[0].split('#')[0]
|
|
31
|
+
_meta.route = get(req, 'routeOptions.url')
|
|
32
|
+
_meta.template = tpl
|
|
33
|
+
_meta.hostHeader = req.headers.host
|
|
34
|
+
_meta.statusCode = 200
|
|
35
|
+
if (params.error) {
|
|
36
|
+
if (params.error.statusCode) _meta.statusCode = params.error.statusCode
|
|
37
|
+
_meta.errorMessage = params.error.message
|
|
38
|
+
}
|
|
39
|
+
if (reply && req.session && req.flash && !opts.partial) _meta.flash = reply.flash()
|
|
40
|
+
const merged = merge({}, params, { _meta })
|
|
41
|
+
await runHook(`${this.name}:afterBuildLocals`, merged, req)
|
|
42
|
+
if (!isEmpty(routeOpts.ns)) await runHook(`${this.name}.${routeOpts.ns}:afterBuildLocals`, merged, req)
|
|
43
|
+
return merged
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default buildLocals
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import compress from '@fastify/compress'
|
|
2
2
|
|
|
3
3
|
async function handleCompress (ctx, options = {}) {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const { defaultsDeep } = this.app.bajo
|
|
5
|
+
if (options === false) return this.log.warn('middlewareDisabled%s', 'compress')
|
|
6
|
+
const opts = defaultsDeep(options, this.app.waibu.config.compress)
|
|
7
|
+
await ctx.register(compress, opts)
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
export default handleCompress
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import cors from '@fastify/cors'
|
|
2
2
|
|
|
3
3
|
async function handleCors (ctx, options = {}) {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const { defaultsDeep } = this.app.bajo
|
|
5
|
+
if (options === false) return this.log.warn('middlewareDisabled%s', 'cors')
|
|
6
|
+
const opts = defaultsDeep(options, this.app.waibu.config.cors)
|
|
7
|
+
await ctx.register(cors, opts)
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
export default handleCors
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import helmet from '@fastify/helmet'
|
|
2
2
|
|
|
3
3
|
async function handleHelmet (ctx, options = {}) {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const { defaultsDeep } = this.app.bajo
|
|
5
|
+
if (options === false) return this.log.warn('middlewareDisabled%s', 'helmet')
|
|
6
|
+
const opts = defaultsDeep(options, this.app.waibu.config.helmet)
|
|
7
|
+
await ctx.register(helmet, opts)
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
export default handleHelmet
|
|
@@ -7,7 +7,7 @@ const pump = promisify(pipeline)
|
|
|
7
7
|
async function onFileHandler () {
|
|
8
8
|
const { getPluginDataDir } = this.app.bajo
|
|
9
9
|
const { fs } = this.app.bajo.lib
|
|
10
|
-
const dir = `${getPluginDataDir(
|
|
10
|
+
const dir = `${getPluginDataDir('waibu')}/upload`
|
|
11
11
|
return async function (part) {
|
|
12
12
|
// 'this' is the fastify context here
|
|
13
13
|
const filePath = `${dir}/${this.id}/${part.fieldname}@${part.filename}`
|
|
@@ -20,7 +20,8 @@ async function handleMultipartBody (ctx, options = {}) {
|
|
|
20
20
|
const { defaultsDeep, importPkg, isSet } = this.app.bajo
|
|
21
21
|
const { isArray, map, trim, isPlainObject, isEmpty } = this.app.bajo.lib._
|
|
22
22
|
const parseVar = await importPkg('dotenv-parse-variables')
|
|
23
|
-
|
|
23
|
+
if (options === false) return this.log.warn('middlewareDisabled%s', 'multipart')
|
|
24
|
+
const opts = defaultsDeep(options, this.app.waibu.config.multipart)
|
|
24
25
|
const onFile = await onFileHandler.call(this)
|
|
25
26
|
opts.onFile = onFile
|
|
26
27
|
await ctx.register(multipart, opts)
|
|
@@ -2,8 +2,10 @@ import rateLimit from '@fastify/rate-limit'
|
|
|
2
2
|
|
|
3
3
|
async function handleRateLimit (ctx, options = {}) {
|
|
4
4
|
const { cloneDeep } = this.app.bajo.lib._
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const { defaultsDeep } = this.app.bajo
|
|
6
|
+
if (options === false) return this.log.warn('middlewareDisabled%s', 'rateLimit')
|
|
7
|
+
const opts = defaultsDeep(options, this.app.waibu.config.rateLimit)
|
|
8
|
+
await ctx.register(rateLimit, cloneDeep(opts))
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
export default handleRateLimit
|