waibu 2.16.2 → 2.18.0

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.
@@ -8,7 +8,7 @@
8
8
  "bootApp%s": "Boot app: %s",
9
9
  "cantParseXmlBodyWithout%s": "Can't parse XML body unless package '%s' is loaded first",
10
10
  "routesL": "routes",
11
- "routeDisabled%s%s": "Route %s (%s) is disabled",
11
+ "routeDisabled%s": "Route '%s' is disabled",
12
12
  "rerouted%s%s": "Rerouted %s -> %s",
13
13
  "bootSubApp%s": "Boot sub app: %s",
14
14
  "routeNotFound%s%s": "Route '%s (%s)' not found",
@@ -8,7 +8,7 @@
8
8
  "bootApp%s": "Jalankan aplikasi: %s",
9
9
  "cantParseXmlBodyWithout%s": "Tidak bisa memparse bodi XML sebelum paket '%s' dimuat terlebih dahulu",
10
10
  "routesL": "jalur",
11
- "routeDisabled%s%s": "Jalur %s (%s) dimatikan",
11
+ "routeDisabled%s": "Jalur '%s' dimatikan",
12
12
  "rerouted%s%s": "Jalur dipindahkan %s -> %s",
13
13
  "bootSubApp%s": "Boot sub app: %s",
14
14
  "routeNotFound%s%s": "Jalur '%s (%s)' tidak ditemukan",
package/index.js CHANGED
@@ -110,7 +110,10 @@ async function factory (pkgName) {
110
110
  lang: 'lang'
111
111
  },
112
112
  paramsCharMap: {},
113
- printRoutes: true,
113
+ route: {
114
+ print: true,
115
+ disabled: []
116
+ },
114
117
  pageTitleFormat: '%s : %s',
115
118
  siteInfo: {
116
119
  title: 'My Website',
@@ -184,7 +187,7 @@ async function factory (pkgName) {
184
187
  }
185
188
  cfg.factory.genReqId = req => generateId()
186
189
  cfg.factory.disableRequestLogging = true
187
- cfg.factory.querystringParser = str => this.qs.parse(str)
190
+ cfg.factory.routerOptions.querystringParser = str => this.qs.parse(str)
188
191
 
189
192
  this.instance = fastify(cfg.factory)
190
193
  this.routes = this.routes || []
@@ -201,7 +204,7 @@ async function factory (pkgName) {
201
204
  await handleHome.call(this)
202
205
  await handleNotFound.call(this)
203
206
  await this.instance.listen(cfg.server)
204
- if (cfg.printRoutes) printRoutes.call(this)
207
+ if (cfg.route.print) printRoutes.call(this)
205
208
  }
206
209
 
207
210
  /**
@@ -391,10 +394,9 @@ async function factory (pkgName) {
391
394
  * @returns {(Object|Array)} - Returns object if ```returnDir``` is ```true```, array of files otherwise
392
395
  */
393
396
  getUploadedFiles = async (reqId, fileUrl = false, returnDir = false) => {
394
- const { getPluginDataDir } = this.app.bajo
395
397
  const { resolvePath } = this.app.lib.aneka
396
398
  const { fastGlob } = this.app.lib
397
- const dir = `${getPluginDataDir(this.ns)}/upload/${reqId}`
399
+ const dir = `${this.app.getPluginDataDir(this.ns)}/upload/${reqId}`
398
400
  const result = await fastGlob(`${dir}/*`)
399
401
  if (!fileUrl) return returnDir ? { dir, files: result } : result
400
402
  const files = result.map(f => resolvePath(f, true))
@@ -468,16 +470,17 @@ async function factory (pkgName) {
468
470
  * @returns {string}
469
471
  */
470
472
  routePath = (name = '', options = {}) => {
471
- const { getPlugin } = this.app.bajo
472
473
  const { defaultsDeep } = this.app.lib.aneka
473
474
  const { isEmpty, get, trimEnd, trimStart } = this.app.lib._
474
475
  const { breakNsPath } = this.app.bajo
475
476
  const { query = {}, ns = this.ns, params = {}, guessHost, defaults = {}, uriEncoded } = options
476
477
 
477
- const plugin = getPlugin(ns)
478
+ const plugin = this.app.getPlugin(ns)
478
479
  const cfg = plugin.config ?? {}
479
480
  let info = {}
481
+ const neg = name[0] === '!'
480
482
  if (name.startsWith('mailto:') || name.startsWith('tel:')) return name
483
+ if (neg) name = name.slice(1)
481
484
  if (name.slice(0, 2) === ':/') name = ns + name
482
485
  if (['%', '.', '/', '?', '#'].includes(name[0]) || name.slice(1, 2) === ':') info.path = name
483
486
  else if (['~'].includes(name[0])) info.path = name.slice(1)
@@ -485,8 +488,8 @@ async function factory (pkgName) {
485
488
  info = breakNsPath(name)
486
489
  }
487
490
  if (info.path.slice(0, 2) === './') info.path = info.path.slice(2)
488
- if (this.routePathHandlers[info.subNs]) return this.routePathHandlers[info.subNs].handler(name, options)
489
- if (info.path.includes('//')) return info.path
491
+ if (this.routePathHandlers[info.subNs]) return (neg ? '!' : '') + this.routePathHandlers[info.subNs].handler(name, options)
492
+ if (info.path.includes('//')) return (neg ? '!' : '') + info.path
490
493
 
491
494
  info.path = info.path.split('/').map(p => {
492
495
  if (!(p[0] === ':' || (p[0] === '{' && p[p.length - 1] === '}'))) return p
@@ -503,7 +506,7 @@ async function factory (pkgName) {
503
506
  info.qs = defaultsDeep({}, query, info.qs)
504
507
  if (!isEmpty(info.qs)) url += '?' + this.qs.stringify(info.qs)
505
508
  if (!url.startsWith('http') && guessHost) url = `http://${this.config.server.host}:${this.config.server.port}/${trimStart(url, '/')}`
506
- return url
509
+ return (neg ? '!' : '') + url
507
510
  }
508
511
 
509
512
  /**
@@ -605,6 +608,16 @@ async function factory (pkgName) {
605
608
  if (isPlainObject(cfgValue) || isArray(cfgValue)) return defaultsDeep({}, reqValue, cfgValue, defValue)
606
609
  return reqValue ?? cfgValue ?? defValue
607
610
  }
611
+
612
+ isRouteDisabled = (path, warning = true) => {
613
+ const { outmatch } = this.app.lib
614
+ path = this.routePath(path)
615
+ const result = this.config.route.disabled.find(item => {
616
+ return outmatch(this.routePath(item))(path)
617
+ })
618
+ if (result && warning) this.log.warn('routeDisabled%s', path)
619
+ return result
620
+ }
608
621
  }
609
622
 
610
623
  return Waibu
@@ -1,10 +1,9 @@
1
1
  export function writeHtml (req, reply, tpl, payload) {
2
- const { getPluginFile } = this.app.bajo
3
2
  const { fs } = this.app.lib
4
3
  const { template } = this.app.lib._
5
4
  reply.header('Content-Type', 'text/html')
6
5
  reply.header('Content-Language', req.lang)
7
- const file = getPluginFile(tpl)
6
+ const file = this.app.getPluginFile(tpl)
8
7
  const content = fs.readFileSync(file, 'utf8')
9
8
  const compiled = template(content)
10
9
  return compiled(payload)
package/lib/web-app.js CHANGED
@@ -8,7 +8,7 @@ export async function collect (glob = 'boot.js', baseNs) {
8
8
  const { ns, alias, config } = this
9
9
  const mod = await importModule(file, { asHandler: true })
10
10
  mod.prefix = get(config, 'waibu.prefix', alias)
11
- if (get(config, 'intl.detectors', []).includes('path')) mod.prefix = `/:lang${mod.prefix}`
11
+ if (get(config, 'intl.detectors', []).includes('path')) mod.prefix = `:lang${mod.prefix === '' ? '' : ('/' + mod.prefix)}`
12
12
  mod.ns = ns
13
13
  mod.alias = alias
14
14
  mods.push(mod)
@@ -28,11 +28,6 @@ async function webApp () {
28
28
  await runHook(`${this.ns}:beforeAppBoot`)
29
29
  // build routes
30
30
  for (const m of this.webApps) {
31
- const disabled = this.app[m.ns].config.disabled
32
- if (Array.isArray(disabled) && disabled.length === 1 && ['*', 'all'].includes(disabled[0])) {
33
- this.log.warn('allRoutesConfigDisabled%s', m.ns)
34
- continue
35
- }
36
31
  const plugin = this.app[m.ns]
37
32
  await runHook(`${this.ns}.${m.ns}:beforeAppBoot`)
38
33
  this.log.debug('bootApp%s', m.ns)
@@ -13,9 +13,8 @@ function normalizeValue (value) {
13
13
  }
14
14
 
15
15
  async function onFileHandler () {
16
- const { getPluginDataDir } = this.app.bajo
17
16
  const { fs } = this.app.lib
18
- const dir = `${getPluginDataDir('waibu')}/upload`
17
+ const dir = `${this.app.getPluginDataDir('waibu')}/upload`
19
18
  return async function (part) {
20
19
  // 'this' is the fastify context here
21
20
  const filePath = `${dir}/${this.id}/${part.fieldname}@${part.filename}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waibu",
3
- "version": "2.16.2",
3
+ "version": "2.18.0",
4
4
  "description": "Web Framework for Bajo",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wiki/CHANGES.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-06-12
4
+
5
+ - [2.18.0] Necessary updates to ```bajo@2.18.0``` specs
6
+
7
+ ## 2026-06-10
8
+
9
+ - [2.17.0] Add ```config.print```
10
+ - [2.17.0] Bug fix in ```factory.routeOptions```
11
+ - [2.17.0] Add support for inversed route in ```routePath()```
12
+ - [2.17.0] Disabled routes now handled directly by ```waibu```, not its web apps
13
+
3
14
  ## 2026-06-05
4
15
 
5
16
  - [2.16.2] Bug fix in ```build-locals.js```
@@ -1,33 +0,0 @@
1
- function santizeMethods (methods = '*') {
2
- if (['*', 'all'].includes(methods)) methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
3
- else methods = methods.split(',').map(s => s.trim())
4
- return methods
5
- }
6
-
7
- async function isRouteDisabled (url, method, matchers = []) {
8
- const { outmatch } = this.app.lib
9
- const { isString, intersection, cloneDeep } = this.app.lib._
10
- const items = []
11
- for (let m of cloneDeep(matchers)) {
12
- if (isString(m)) m = { path: m }
13
- try {
14
- m.path = this.app.waibu.routePath(m.path)
15
- m.methods = santizeMethods(m.methods)
16
- items.push(m)
17
- } catch (err) {
18
- throw this.error(`${m.path}: ${err.message}`)
19
- }
20
- }
21
- const matcher = items.find(i => {
22
- const isMatch = outmatch(i.path)
23
- return isMatch(url)
24
- })
25
- if (!matcher) return false
26
- if (Array.isArray(method)) {
27
- const result = intersection(method, matcher.methods)
28
- return result.length > 0
29
- }
30
- return matcher.methods.includes(method)
31
- }
32
-
33
- export default isRouteDisabled