miolo 3.0.0-beta.21 → 3.0.0-beta.210

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.
Files changed (246) hide show
  1. package/bin/build/build.mjs +53 -0
  2. package/bin/build/build_bin.mjs +17 -0
  3. package/bin/build/cli/client.mjs +52 -0
  4. package/bin/build/cli/css.mjs +22 -0
  5. package/bin/build/cli/index.mjs +40 -0
  6. package/bin/build/cli/ssr.mjs +21 -0
  7. package/bin/build/server/aliases.mjs +112 -0
  8. package/bin/build/server/babel.config.js +24 -0
  9. package/bin/build/server/banner.mjs +20 -0
  10. package/bin/build/server/bundle.mjs +111 -0
  11. package/bin/build/server/fix.mjs +15 -0
  12. package/bin/build/server/index.mjs +69 -0
  13. package/bin/build/server/options.mjs +83 -0
  14. package/bin/create/auth.mjs +23 -0
  15. package/bin/create/copy.mjs +175 -0
  16. package/bin/create/docker.mjs +25 -0
  17. package/bin/create/index.mjs +137 -0
  18. package/bin/create/pkgjson.mjs +72 -0
  19. package/bin/create/prepare-template.mjs +158 -0
  20. package/bin/create/validation.mjs +27 -0
  21. package/bin/dev/dev.mjs +32 -23
  22. package/bin/dev/dev_start.mjs +6 -5
  23. package/bin/index.mjs +94 -52
  24. package/bin/prod-bin/create-bin.mjs +42 -27
  25. package/bin/prod-bin/run.mjs +13 -9
  26. package/bin/{prod-run → run}/pid.mjs +4 -4
  27. package/bin/run/restart.mjs +13 -0
  28. package/bin/run/start.mjs +18 -0
  29. package/bin/run/stop.mjs +20 -0
  30. package/bin/util.mjs +35 -11
  31. package/package.json +59 -39
  32. package/src/config/.env +34 -12
  33. package/src/config/defaults.mjs +253 -185
  34. package/src/config/env.mjs +40 -22
  35. package/src/config/index.mjs +19 -24
  36. package/src/config/util.mjs +25 -10
  37. package/src/db-conn.mjs +34 -0
  38. package/src/engines/cron/emails.mjs +10 -5
  39. package/src/engines/cron/index.mjs +45 -51
  40. package/src/engines/cron/init.mjs +16 -17
  41. package/src/engines/cron/ipsum.mjs +65 -60
  42. package/src/engines/cron/syscheck.mjs +30 -30
  43. package/src/engines/emailer/index.mjs +1 -2
  44. package/src/engines/emailer/queue.mjs +14 -20
  45. package/src/engines/emailer/transporter.mjs +86 -74
  46. package/src/engines/geoip/index.mjs +23 -28
  47. package/src/engines/http/index.mjs +26 -15
  48. package/src/engines/logger/buildErrorEmailBody.mjs +72 -0
  49. package/src/engines/logger/index.mjs +114 -122
  50. package/src/engines/logger/injectStackTrace.mjs +59 -0
  51. package/src/engines/logger/logger_mail.mjs +47 -61
  52. package/src/engines/logger/reopenTransportOnHupSignal.mjs +12 -13
  53. package/src/engines/parser/Parser.mjs +77 -60
  54. package/src/engines/parser/index.mjs +1 -1
  55. package/src/engines/schema/diffObjs.mjs +41 -0
  56. package/src/engines/schema/index.mjs +4 -0
  57. package/src/engines/schema/input.mjs +54 -0
  58. package/src/engines/schema/output.mjs +66 -0
  59. package/src/engines/socket/index.mjs +44 -46
  60. package/src/index.mjs +15 -10
  61. package/src/middleware/auth/basic.mjs +41 -40
  62. package/src/middleware/auth/custom.mjs +10 -13
  63. package/src/middleware/auth/guest.mjs +27 -27
  64. package/src/middleware/auth/passport/index.mjs +374 -0
  65. package/src/middleware/auth/passport/session/index.mjs +43 -0
  66. package/src/middleware/auth/{credentials → passport}/session/store.mjs +35 -15
  67. package/src/middleware/auth/passport/session/store_koa_redis.mjs +3 -0
  68. package/src/middleware/context/cache/index.mjs +78 -33
  69. package/src/middleware/context/cache/options.mjs +19 -21
  70. package/src/middleware/context/db.mjs +45 -20
  71. package/src/middleware/context/index.mjs +12 -12
  72. package/src/middleware/extra.mjs +4 -5
  73. package/src/middleware/http/body.mjs +25 -25
  74. package/src/middleware/http/catcher.mjs +81 -8
  75. package/src/middleware/http/custom_blacklist.mjs +19 -16
  76. package/src/middleware/http/headers.mjs +37 -34
  77. package/src/middleware/http/ratelimit.mjs +16 -23
  78. package/src/middleware/http/request.mjs +60 -65
  79. package/src/middleware/routes/catch_js_error.mjs +30 -23
  80. package/src/middleware/routes/robots.mjs +4 -7
  81. package/src/middleware/routes/router/crud/attachCrudRoutes.mjs +108 -90
  82. package/src/middleware/routes/router/crud/getCrudConfig.mjs +31 -55
  83. package/src/middleware/routes/router/defaults.mjs +6 -19
  84. package/src/middleware/routes/router/index.mjs +17 -21
  85. package/src/middleware/routes/router/queries/attachQueriesRoutes.mjs +227 -50
  86. package/src/middleware/routes/router/queries/getQueriesConfig.mjs +45 -55
  87. package/src/middleware/routes/router/utils.mjs +41 -26
  88. package/src/middleware/ssr/context.mjs +5 -7
  89. package/src/middleware/ssr/html.mjs +66 -43
  90. package/src/middleware/ssr/loader.mjs +11 -14
  91. package/src/middleware/ssr/ssr_render.mjs +39 -22
  92. package/src/middleware/static/index.mjs +33 -14
  93. package/src/middleware/vite/devserver.mjs +38 -22
  94. package/src/middleware/vite/watcher.mjs +12 -14
  95. package/src/server-cron.mjs +13 -8
  96. package/src/server-dev.mjs +13 -16
  97. package/src/server.mjs +49 -51
  98. package/template/.agent/skills/miolo-app-arch/SKILL.md +218 -0
  99. package/template/.agent/skills/miolo-auth/SKILL.md +450 -0
  100. package/template/.agent/skills/miolo-cli-router/SKILL.md +394 -0
  101. package/template/.agent/skills/miolo-database/SKILL.md +358 -0
  102. package/template/.agent/skills/miolo-react-patterns/SKILL.md +426 -0
  103. package/template/.agent/skills/miolo-routing/SKILL.md +326 -0
  104. package/template/.agent/skills/miolo-schemas/SKILL.md +329 -0
  105. package/template/.agent/skills/miolo-session-context/SKILL.md +397 -0
  106. package/template/.agent/skills/miolo-ssr/SKILL.md +433 -0
  107. package/template/.editorconfig +18 -0
  108. package/template/.env +120 -0
  109. package/template/biome.json +63 -0
  110. package/template/components.json +21 -0
  111. package/template/db/init.sh +89 -0
  112. package/template/db/sql/00_drop.sql +2 -0
  113. package/template/db/sql/01_users.sql +31 -0
  114. package/template/db/sql/02_todos.sql +20 -0
  115. package/template/docker/Dockerfile +13 -0
  116. package/template/docker/docker-compose.yaml +79 -0
  117. package/template/gitignore +42 -0
  118. package/template/jsconfig.json +18 -0
  119. package/template/package.json +88 -0
  120. package/template/postcss.config.js +9 -0
  121. package/template/src/cli/App.jsx +25 -0
  122. package/template/src/cli/components/JsonTreeViewer.jsx +128 -0
  123. package/template/src/cli/components/shadcn-io/spinner/index.jsx +232 -0
  124. package/template/src/cli/components/stepper.jsx +408 -0
  125. package/template/src/cli/components/ui/avatar.jsx +36 -0
  126. package/template/src/cli/components/ui/badge.jsx +31 -0
  127. package/template/src/cli/components/ui/breadcrumb.jsx +97 -0
  128. package/template/src/cli/components/ui/card.jsx +73 -0
  129. package/template/src/cli/components/ui/collapsible.jsx +16 -0
  130. package/template/src/cli/components/ui/dropdown-menu.jsx +179 -0
  131. package/template/src/cli/components/ui/field.jsx +217 -0
  132. package/template/src/cli/components/ui/input.jsx +19 -0
  133. package/template/src/cli/components/ui/label.jsx +17 -0
  134. package/template/src/cli/components/ui/pagination.jsx +99 -0
  135. package/template/src/cli/components/ui/patched/alert.jsx +56 -0
  136. package/template/src/cli/components/ui/patched/button.jsx +45 -0
  137. package/template/src/cli/components/ui/patched/dialog.jsx +114 -0
  138. package/template/src/cli/components/ui/patched/sidebar.jsx +660 -0
  139. package/template/src/cli/components/ui/select.jsx +141 -0
  140. package/template/src/cli/components/ui/separator.jsx +21 -0
  141. package/template/src/cli/components/ui/sheet.jsx +115 -0
  142. package/template/src/cli/components/ui/skeleton.jsx +13 -0
  143. package/template/src/cli/components/ui/sonner.jsx +22 -0
  144. package/template/src/cli/components/ui/switch.jsx +25 -0
  145. package/template/src/cli/components/ui/table.jsx +88 -0
  146. package/template/src/cli/components/ui/textarea.jsx +16 -0
  147. package/template/src/cli/components/ui/tooltip.jsx +45 -0
  148. package/template/src/cli/config/store_keys.mjs +2 -0
  149. package/template/src/cli/context/data/DataContext.jsx +5 -0
  150. package/template/src/cli/context/data/DataProvider.jsx +44 -0
  151. package/template/src/cli/context/data/useBreads.mjs +15 -0
  152. package/template/src/cli/context/data/useDataContext.mjs +4 -0
  153. package/template/src/cli/context/session/SessionContext.mjs +4 -0
  154. package/template/src/cli/context/session/SessionProvider.jsx +31 -0
  155. package/template/src/cli/context/session/makePermissioner.mjs +34 -0
  156. package/template/src/cli/context/session/useSessionContext.mjs +6 -0
  157. package/template/src/cli/context/theme/ThemeContext.mjs +4 -0
  158. package/template/src/cli/context/theme/ThemeProvider.jsx +49 -0
  159. package/template/src/cli/context/theme/useThemeContext.mjs +6 -0
  160. package/template/src/cli/context/ui/UIContext.jsx +5 -0
  161. package/template/src/cli/context/ui/UIProvider.jsx +16 -0
  162. package/template/src/cli/context/ui/useUIContext.mjs +4 -0
  163. package/template/src/cli/context/util.mjs +17 -0
  164. package/template/src/cli/entry-cli.jsx +33 -0
  165. package/template/src/cli/hooks/useIsMobile.mjs +19 -0
  166. package/template/src/cli/hooks/useStoragedState.mjs +63 -0
  167. package/template/src/cli/index.html +29 -0
  168. package/template/src/cli/layout/app-sidebar.jsx +25 -0
  169. package/template/src/cli/layout/main-layout.jsx +63 -0
  170. package/template/src/cli/layout/nav-last-todos.jsx +72 -0
  171. package/template/src/cli/layout/nav-main.jsx +39 -0
  172. package/template/src/cli/layout/nav-user.jsx +105 -0
  173. package/template/src/cli/layout/prop-switcher.jsx +93 -0
  174. package/template/src/cli/lib/utils.mjs +10 -0
  175. package/template/src/cli/pages/Index.jsx +13 -0
  176. package/template/src/cli/pages/IndexOffline.jsx +13 -0
  177. package/template/src/cli/pages/IndexOnline.jsx +18 -0
  178. package/template/src/cli/pages/dash/Dashboard.jsx +29 -0
  179. package/template/src/cli/pages/offline/Login.jsx +43 -0
  180. package/template/src/cli/pages/offline/LoginForm.jsx +115 -0
  181. package/template/src/cli/pages/security/Security.jsx +39 -0
  182. package/template/src/cli/pages/security/SecurityForm.jsx +106 -0
  183. package/template/src/cli/pages/todos/TodoActions.jsx +99 -0
  184. package/template/src/cli/pages/todos/TodoAdd.jsx +43 -0
  185. package/template/src/cli/pages/todos/TodoList.jsx +60 -0
  186. package/template/src/cli/pages/todos/Todos.jsx +23 -0
  187. package/template/src/cli/pages/todos/context/TodosContext.jsx +5 -0
  188. package/template/src/cli/pages/todos/context/TodosProvider.jsx +191 -0
  189. package/template/src/cli/pages/todos/context/useTodosContext.mjs +4 -0
  190. package/template/src/ns/models/Todo.mjs +29 -0
  191. package/template/src/ns/models/TodoList.mjs +8 -0
  192. package/template/src/ns/models/User.mjs +40 -0
  193. package/template/src/server/bot/check_today.mjs +10 -0
  194. package/template/src/server/io/cache/base.mjs +21 -0
  195. package/template/src/server/io/db/filter.mjs +92 -0
  196. package/template/src/server/io/db/todos/delete.mjs +29 -0
  197. package/template/src/server/io/db/todos/find.mjs +13 -0
  198. package/template/src/server/io/db/todos/read.mjs +83 -0
  199. package/template/src/server/io/db/todos/toggle.mjs +37 -0
  200. package/template/src/server/io/db/todos/upsave.mjs +32 -0
  201. package/template/src/server/io/db/triggers/user.mjs +13 -0
  202. package/template/src/server/io/db/users/auth.mjs +132 -0
  203. package/template/src/server/io/db/users/pwd.mjs +38 -0
  204. package/template/src/server/io/db/users/save.mjs +17 -0
  205. package/template/src/server/miolo/auth/basic.mjs +15 -0
  206. package/template/src/server/miolo/auth/guest.mjs +3 -0
  207. package/template/src/server/miolo/auth/passport.mjs +73 -0
  208. package/template/src/server/miolo/cache.mjs +11 -0
  209. package/template/src/server/miolo/cron/foo.mjs +7 -0
  210. package/template/src/server/miolo/cron/index.mjs +28 -0
  211. package/template/src/server/miolo/cron/invalidate.mjs +21 -0
  212. package/template/src/server/miolo/db.mjs +36 -0
  213. package/template/src/server/miolo/http.mjs +14 -0
  214. package/template/src/server/miolo/index.mjs +43 -0
  215. package/template/src/server/miolo/routes/crud.mjs +16 -0
  216. package/template/src/server/miolo/routes/index.mjs +8 -0
  217. package/template/src/server/miolo/ssr/entry-server.jsx +13 -0
  218. package/template/src/server/miolo/ssr/loader.mjs +18 -0
  219. package/template/src/server/routes/index.mjs +66 -0
  220. package/template/src/server/routes/todos/mod.mjs +52 -0
  221. package/template/src/server/routes/todos/read.mjs +45 -0
  222. package/template/src/server/routes/todos/special.mjs +47 -0
  223. package/template/src/server/routes/users/user.mjs +54 -0
  224. package/template/src/server/server.mjs +10 -0
  225. package/template/src/server/utils/crypt.mjs +38 -0
  226. package/template/src/server/utils/io.mjs +15 -0
  227. package/template/src/server/utils/pwdfor.mjs +25 -0
  228. package/template/src/server/utils/schema.mjs +22 -0
  229. package/template/src/static/img/default/profile.png +0 -0
  230. package/template/src/static/img/favicon.ico +0 -0
  231. package/template/src/static/img/miolo_logo.png +0 -0
  232. package/template/src/static/img/miolo_name.png +0 -0
  233. package/template/src/static/public/manifest.json +21 -0
  234. package/template/src/static/public/sw.js +79 -0
  235. package/template/src/static/style/globals.css +156 -0
  236. package/template/src/static/style/json-tree.css +54 -0
  237. package/template/src/static/style/skeleton.css +49 -0
  238. package/bin/prod-build/build-client.mjs +0 -67
  239. package/bin/prod-build/build-server.mjs +0 -58
  240. package/bin/prod-run/restart.mjs +0 -9
  241. package/bin/prod-run/start.mjs +0 -15
  242. package/bin/prod-run/stop.mjs +0 -20
  243. package/src/engines/logger/verify.mjs +0 -22
  244. package/src/middleware/auth/credentials/index.mjs +0 -151
  245. package/src/middleware/auth/credentials/session/index.mjs +0 -24
  246. package/src/middleware/auth/credentials/session/store_koa_redis.mjs +0 -3
@@ -1,21 +1,25 @@
1
- import { performance } from 'perf_hooks'
2
- import { cyan, green, yellow, red, magenta, cyan_light } from 'tinguir'
1
+ import { performance } from "node:perf_hooks"
2
+ import { cyan, cyan_light, green, magenta, red, yellow } from "tinguir"
3
3
 
4
- import { geoip_localize_ip } from '../../engines/geoip/index.mjs'
4
+ import { geoip_localize_ip } from "../../engines/geoip/index.mjs"
5
5
 
6
- let REQUEST_COUNTER= {
6
+ const REQUEST_COUNTER = {
7
7
  total: 0
8
8
  }
9
9
 
10
- function _validate_ip(ipaddress) {
11
- if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress)) {
10
+ function _validate_ip(ipaddress) {
11
+ if (
12
+ /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(
13
+ ipaddress
14
+ )
15
+ ) {
12
16
  return true
13
17
  }
14
18
  return false
15
19
  }
16
20
 
17
21
  const _get_ip = (ctx) => {
18
- const chances = [ctx.headers["x-real-ip"], ctx.headers["x-orig-ip"], ctx.ip, '127.0.0.1']
22
+ const chances = [ctx.headers["x-real-ip"], ctx.headers["x-orig-ip"], ctx.ip, "127.0.0.1"]
19
23
  for (const ch of chances) {
20
24
  if (_validate_ip(ch)) {
21
25
  return ch
@@ -28,12 +32,12 @@ const _get_ip = (ctx) => {
28
32
  */
29
33
 
30
34
  function init_request_middleware(app, config) {
35
+ const _def_on_begin = async (_ctx, _times) => {
36
+ return {}
37
+ }
38
+ const _def_on_done = async (_ctx, _begin_result, _times) => {}
31
39
 
32
- /* eslint-disable no-unused-vars */
33
- const _def_on_begin = async (ctx, times) => { return {} }
34
- const _def_on_done = async (ctx, begin_result, times) => { }
35
-
36
- let reqConfig = {
40
+ const reqConfig = {
37
41
  lazy: config?.lazy || 1,
38
42
  slow: config?.slow || 2,
39
43
  onStart: config?.onStart || _def_on_begin,
@@ -43,18 +47,17 @@ function init_request_middleware(app, config) {
43
47
  }
44
48
  }
45
49
 
46
-
47
50
  async function request_middleware(ctx, next) {
48
51
  const logger = ctx.miolo.logger
49
52
  const ip = _get_ip(ctx)
50
53
  const started = performance.now()
51
-
54
+
52
55
  // Keep request counters
53
- REQUEST_COUNTER.total+= 1
56
+ REQUEST_COUNTER.total += 1
54
57
  REQUEST_COUNTER[ip] = (REQUEST_COUNTER[ip] || 0) + 1
55
-
58
+
56
59
  // Attach some info to request
57
- ctx.requestId= REQUEST_COUNTER.total
60
+ ctx.requestId = REQUEST_COUNTER.total
58
61
  ctx.request.ip = ip
59
62
 
60
63
  // If wanted, geo localize ip
@@ -66,81 +69,73 @@ function init_request_middleware(app, config) {
66
69
  ctx.request.geoip = geo_info
67
70
 
68
71
  // Log something
69
- const clurl = ctx.request.url.indexOf('?')>=0
70
- ? ctx.request.url.substr(0, ctx.request.url.indexOf('?'))
71
- : ctx.request.url
72
- const geo_string = geo_enabled
73
- ? geo_info?.local === true
74
- ? ''
75
- : geo_info?.country
76
- ? geo_info?.city
77
- ? ` (${geo_info?.city}, ${geo_info.country})`
78
- : ` (${geo_info.country})`
79
- : ''
80
- : ''
72
+ const clurl =
73
+ ctx.request.url.indexOf("?") >= 0
74
+ ? ctx.request.url.substr(0, ctx.request.url.indexOf("?"))
75
+ : ctx.request.url
76
+ const geo_string = geo_enabled
77
+ ? geo_info?.local === true
78
+ ? ""
79
+ : geo_info?.country
80
+ ? geo_info?.city
81
+ ? ` (${geo_info?.city}, ${geo_info.country})`
82
+ : ` (${geo_info.country})`
83
+ : ""
84
+ : ""
81
85
  const sreq = `${magenta(ip)}${geo_string} ${cyan(ctx.request.method)} ${cyan(clurl)} [${cyan_light(REQUEST_COUNTER[ip])}/${cyan_light(ctx.requestId)}]`
82
- const sbody= ctx.request.body!=undefined ? JSON.stringify(ctx.request.body) : ''
83
-
86
+ const sbody = ctx.request.body !== undefined ? JSON.stringify(ctx.request.body) : ""
87
+
84
88
  logger.info(`${sreq} - START`)
85
89
  logger.debug(`${sreq} - Body: ${sbody}`)
86
90
 
87
- const begin_result = await reqConfig.onStart(ctx, {started, description: 'pending'})
91
+ const begin_result = await reqConfig.onStart(ctx, { started, description: "pending" })
88
92
 
89
- await next()
93
+ await next()
90
94
 
91
95
  const user = ctx?.session?.user
92
- let uid_desc= ''
93
- if (user != undefined) {
96
+ let uid_desc = ""
97
+ if (user !== undefined && user !== null) {
94
98
  if (user?.id) {
95
- uid_desc= ` - uid ${user?.id}`
99
+ uid_desc = ` - uid ${user?.id}`
96
100
  } else if (user?.token) {
97
- uid_desc= ` - token ${user?.token}`
101
+ uid_desc = ` - token ${user?.token}`
98
102
  }
99
103
  }
100
104
  const status = ctx.response.status
101
- let ststr= status
105
+ let ststr = status
102
106
  let stcolor
103
- if (status==200) {
104
- stcolor= green
105
- } else if (status>200 && status<=299) {
106
- stcolor= yellow
107
+ if (status === 200) {
108
+ stcolor = green
109
+ } else if (status > 200 && status <= 299) {
110
+ stcolor = yellow
107
111
  if (ctx.response.redirected && ctx.response.url) {
108
- ststr+= ` -> ${ctx.response.url}`
109
-
112
+ ststr += ` -> ${ctx.response.url}`
110
113
  }
111
114
  } else {
112
- stcolor= red
115
+ stcolor = red
113
116
  }
114
117
  const stdesc = `[${stcolor(ststr)}]`
115
118
 
116
- const elapsed = parseFloat( (performance.now() - started) / 1000.0 ).toFixed(2)
117
-
118
- const tcolor= elapsed < reqConfig.lazy
119
- ? green
120
- : elapsed < reqConfig.slow
121
- ? yellow
122
- : red
123
-
124
- const tname= elapsed < reqConfig.lazy
125
- ? 'Ok'
126
- : elapsed < reqConfig.slow
127
- ? 'lazy'
128
- : 'slow'
129
-
130
- const ssession= ctx.session!=undefined ? JSON.stringify(ctx.session) : ''
119
+ const elapsed = parseFloat((performance.now() - started) / 1000.0).toFixed(2)
120
+
121
+ const tcolor = elapsed < reqConfig.lazy ? green : elapsed < reqConfig.slow ? yellow : red
122
+
123
+ const tname = elapsed < reqConfig.lazy ? "Ok" : elapsed < reqConfig.slow ? "lazy" : "slow"
124
+
125
+ const ssession = ctx.session !== undefined ? JSON.stringify(ctx.session) : ""
131
126
  logger.debug(`${sreq} - Session: ${ssession.slice(0, 150)}...`)
132
127
  logger.silly(`${sreq} - Session: ${ssession}`)
133
128
 
134
- const rbody= ctx.body!=undefined ? JSON.stringify(ctx.body) : ''
129
+ const rbody = ctx.body !== undefined ? JSON.stringify(ctx.body) : ""
135
130
  logger.debug(`${sreq} - Response: ${rbody.slice(0, 150)}...`)
136
131
  logger.silly(`${sreq} - Response: ${rbody}`)
137
132
 
138
- await reqConfig.onDone(ctx, begin_result, {started, elapsed, description: tname})
139
-
133
+ await reqConfig.onDone(ctx, begin_result, { started, elapsed, description: tname })
134
+
140
135
  logger.info(`${sreq} - DONE ${stdesc}${uid_desc} (${tcolor(tname)}: ${tcolor(elapsed)})`)
141
136
  }
142
-
137
+
143
138
  app.use(request_middleware)
144
139
  }
145
140
 
146
- export {init_request_middleware}
141
+ export { init_request_middleware }
@@ -1,41 +1,48 @@
1
- import { blue, red, yellow } from 'tinguir'
2
- import Router from '@koa/router'
1
+ import Router from "@koa/router"
2
+ import { blue, red, yellow } from "tinguir"
3
+
4
+ const ERRORS_AS_WARNINGS = ["Minified React error"]
3
5
 
4
6
  function init_route_catch_js_error(app, route) {
5
-
6
7
  async function catch_js_error(ctx) {
7
- const { error, warning, path, agent } = ctx.request.body
8
+ let { error, warning, path, agent } = ctx.request.body
8
9
  const logger = ctx.miolo.logger
9
10
 
11
+ if (error) {
12
+ ERRORS_AS_WARNINGS.forEach((e) => {
13
+ if (error.msg.indexOf(e) >= 0) {
14
+ warning = error
15
+ }
16
+ })
17
+ }
18
+
10
19
  if (warning) {
11
- const msg=
12
- `${yellow('[JS Warning]')} on ${blue(path)}: ${JSON.stringify(warning.msg)}\n` +
13
- `${yellow('[JS Warning]')} File => ${warning.file}\n` +
14
- `${yellow('[JS Warning]')} Line => ${warning.line}\n` +
15
- `${yellow('[JS Warning]')} Col => ${warning.col}\n` +
16
- `${yellow('[JS Warning]')} Error => ${JSON.stringify(warning.error)}\n` +
17
- `${yellow('[JS Warning]')} Agent => ${agent}`
20
+ const msg =
21
+ `${yellow("[JS Warning]")} on ${blue(path)}: ${JSON.stringify(warning.msg)}\n` +
22
+ `${yellow("[JS Warning]")} File => ${warning.file}\n` +
23
+ `${yellow("[JS Warning]")} Line => ${warning.line}\n` +
24
+ `${yellow("[JS Warning]")} Col => ${warning.col}\n` +
25
+ `${yellow("[JS Warning]")} Error => ${JSON.stringify(warning.error)}\n` +
26
+ `${yellow("[JS Warning]")} Agent => ${agent}`
18
27
  logger.warn(msg)
19
-
20
28
  } else {
21
- const msg=
22
- `${red('[JS Error]')} on ${blue(path)}: ${JSON.stringify(error.msg)}\n` +
23
- `${red('[JS Error]')} File => ${error.file}\n` +
24
- `${red('[JS Error]')} Line => ${error.line}\n` +
25
- `${red('[JS Error]')} Col => ${error.col}\n` +
26
- `${red('[JS Error]')} Error => ${JSON.stringify(error.error)}\n` +
27
- `${red('[JS Error]')} Agent => ${agent}`
29
+ const msg =
30
+ `${red("[JS Error]")} on ${blue(path)}: ${JSON.stringify(error.msg)}\n` +
31
+ `${red("[JS Error]")} File => ${error.file}\n` +
32
+ `${red("[JS Error]")} Line => ${error.line}\n` +
33
+ `${red("[JS Error]")} Col => ${error.col}\n` +
34
+ `${red("[JS Error]")} Error => ${JSON.stringify(error.error)}\n` +
35
+ `${red("[JS Error]")} Agent => ${agent}`
28
36
  logger.error(msg)
29
37
  }
30
38
 
31
- ctx.body = {result: 1}
39
+ ctx.body = { ok: true, data: 1 }
32
40
  }
33
41
 
34
42
  const catch_js_error_router = new Router()
35
43
  catch_js_error_router.post(route, catch_js_error)
36
-
37
- app.use(catch_js_error_router.routes())
38
44
 
45
+ app.use(catch_js_error_router.routes())
39
46
  }
40
47
 
41
- export {init_route_catch_js_error}
48
+ export { init_route_catch_js_error }
@@ -1,21 +1,18 @@
1
- import Router from '@koa/router'
2
-
1
+ import Router from "@koa/router"
3
2
 
4
3
  const ROBOTS_TXT = `User-agent: *
5
4
  Disallow: /
6
5
  `
7
6
 
8
7
  function init_route_robots(app) {
9
-
10
8
  async function robots(ctx) {
11
9
  ctx.body = ROBOTS_TXT
12
10
  }
13
11
 
14
12
  const robots_router = new Router()
15
- robots_router.get('/robots.txt', robots)
16
-
13
+ robots_router.get("/robots.txt", robots)
14
+
17
15
  app.use(robots_router.routes())
18
16
  }
19
17
 
20
-
21
- export {init_route_robots}
18
+ export { init_route_robots }
@@ -1,214 +1,232 @@
1
- import {query_string_to_json} from '../utils.mjs'
2
-
1
+ import { query_string_to_json } from "../utils.mjs"
3
2
 
4
3
  function attachCrudRoutes(router, crudConfigs, logger) {
5
-
6
- crudConfigs.map((crudConfig) => {
7
-
8
- const prefix= crudConfig.prefix
9
-
10
- crudConfig.routes.map(route => {
4
+ crudConfigs.forEach((crudConfig) => {
5
+ const prefix = crudConfig.prefix
11
6
 
7
+ crudConfig.routes.forEach((route) => {
12
8
  const _pack_body_field = (data) => {
13
- if (route.bodyField == undefined) {
14
- return data
9
+ if (route.bodyField === undefined) {
10
+ return { data }
15
11
  }
16
12
  return {
13
+ bodyField: route.bodyField,
17
14
  [route.bodyField]: data
18
15
  }
19
16
  }
20
-
21
17
 
22
18
  const _crud_auth_callback = async (ctx, op) => {
23
- const authenticated= ctx?.session?.authenticated === true
24
-
19
+ const authenticated = ctx?.session?.authenticated === true
20
+
25
21
  const auth = route.auth
26
- const checkAuth= (auth.require===true) || (auth.require==='read-only' && op==='w')
27
-
22
+ const checkAuth = auth.require === true || (auth.require === "read-only" && op === "w")
23
+
28
24
  if (checkAuth) {
29
-
30
25
  if (!authenticated) {
31
- if (auth.action=='error') {
32
- ctx.miolo.logger.error(`[router] Unauthorized access. Throwing error ${auth.error_code}`)
33
- ctx.throw(
34
- auth.error_code,
35
- 'Unauthorized',
36
- {}
26
+ if (auth.action === "error") {
27
+ ctx.miolo.logger.error(
28
+ `[router] Unauthorized access. Throwing error ${auth.error_code}`
29
+ )
30
+ ctx.throw(auth.error_code, new Error("Unauthorized"), {})
31
+ } else if (auth.action === "redirect") {
32
+ ctx.miolo.logger.warn(
33
+ `[router] Unauthorized access. Redirecting to ${auth.redirect_url}`
37
34
  )
38
- } else if (auth.action=='redirect') {
39
- ctx.miolo.logger.warn(`[router] Unauthorized access. Redirecting to ${auth.redirect_url}`)
35
+ ctx.body = {
36
+ ok: false,
37
+ error: "Unathorized"
38
+ }
40
39
  ctx.redirect(auth.redirect_url)
41
40
  } else {
42
41
  ctx.miolo.logger.error(`[router] Crud path ${route.url} specified auth but no action`)
43
- ctx.body= {}
42
+ ctx.body = {
43
+ ok: false,
44
+ error: "Unathorized"
45
+ }
44
46
  }
45
47
  }
46
48
  return authenticated
47
49
  }
48
-
50
+
49
51
  return true
50
52
  }
51
53
 
52
54
  const _crud_callback = async (ctx, op, callback) => {
53
55
  const model = await ctx.miolo.db.get_model(route.name)
54
56
 
55
- if (! model) {
57
+ if (!model) {
56
58
  ctx.miolo.logger.error(`[router] Could not get model for ${route.name}`)
57
59
  throw new Error(`[router] Could not get model for ${route.name}`)
58
60
  }
59
61
 
60
- let result = {}
62
+ let data = {}
61
63
  try {
62
64
  const authenticated = await _crud_auth_callback(ctx, op)
63
65
 
64
- if (! authenticated) {
65
- ctx.body= {}
66
+ if (!authenticated) {
67
+ ctx.body = {
68
+ ok: false,
69
+ error: "Unathorized"
70
+ }
66
71
  return
67
72
  }
68
-
69
- let goon= true
73
+
74
+ let goon = true
70
75
  if (route?.before) {
71
- goon= await route.before(ctx)
76
+ if (Array.isArray(route.before)) {
77
+ for (const before of route.before) {
78
+ goon = await before(ctx)
79
+ if (!goon) {
80
+ break
81
+ }
82
+ }
83
+ } else {
84
+ goon = await route.before(ctx)
85
+ }
72
86
  }
73
87
 
74
- if (! goon) {
75
- ctx.body= {}
88
+ if (!goon) {
89
+ ctx.body = {
90
+ ok: false,
91
+ error: "Not allowed"
92
+ }
76
93
  return
77
94
  }
78
95
 
79
- const uid= ctx?.session?.user?.id
80
- let fieldNames= {}
81
- if (route.useUserFields.use===true) {
82
- fieldNames= route.useUserFields.fieldNames
96
+ const uid = ctx?.session?.user?.id
97
+ let fieldNames = {}
98
+ if (route.useUserFields.use === true) {
99
+ fieldNames = route.useUserFields.fieldNames
83
100
  }
84
101
 
85
- const uinfo= {
102
+ const uinfo = {
86
103
  uid: uid,
87
- fieldNames,
104
+ fieldNames
88
105
  }
89
-
90
- result= await callback(model, uinfo)
91
-
106
+
107
+ data = await callback(model, uinfo)
108
+
92
109
  if (route?.after) {
93
- result= await route.after(ctx, result)
110
+ if (Array.isArray(route.after)) {
111
+ for (const after of route.after) {
112
+ data = await after(ctx, data)
113
+ }
114
+ } else {
115
+ data = await route.after(ctx, data)
116
+ }
94
117
  }
95
- } catch(error) {
118
+ } catch (error) {
96
119
  ctx.miolo.logger.error(`[router] Unexpected error on CRUD ${route.name}-${op}`)
97
120
  ctx.miolo.logger.error(error)
98
121
  }
99
122
 
100
- result= _pack_body_field(result)
101
-
102
- ctx.body= result
123
+ ctx.body = { ok: true, ..._pack_body_field(data) }
103
124
  }
104
125
 
105
126
  const route_read = async (ctx) => {
106
- await _crud_callback(ctx, 'r', async (model, _uinfo) => {
127
+ await _crud_callback(ctx, "r", async (model, _uinfo) => {
107
128
  const params = query_string_to_json(ctx.request.url)
108
129
  // TODO : handle transactions
109
- const options= {transaction: undefined}
130
+ const options = { transaction: undefined }
110
131
  const data = await model.read(params, options)
111
132
  return data
112
133
  })
113
134
  }
114
-
135
+
115
136
  const route_key_list = async (ctx) => {
116
- await _crud_callback(ctx, 'r', async (model, _uinfo) => {
137
+ await _crud_callback(ctx, "r", async (model, _uinfo) => {
117
138
  // TODO : handle transactions
118
139
  const params = query_string_to_json(ctx.request.url)
119
- const options= {transaction: undefined}
120
- const data = await model.keyList(params, options)
140
+ const options = { transaction: undefined }
141
+ const data = await model.keyList(params, options)
121
142
  return data
122
143
  })
123
144
  }
124
-
145
+
125
146
  const route_find = async (ctx) => {
126
- await _crud_callback(ctx, 'r', async (model, _uinfo) => {
147
+ await _crud_callback(ctx, "r", async (model, _uinfo) => {
127
148
  const params = query_string_to_json(ctx.request.url)
128
149
  // TODO : handle transactions
129
- const options= {transaction: undefined}
150
+ const options = { transaction: undefined }
130
151
  const data = await model.find(params.id, options)
131
152
  return data
132
153
  })
133
154
  }
134
155
 
135
156
  const route_distinct = async (ctx) => {
136
- await _crud_callback(ctx, 'r', async (model, _uinfo) => {
157
+ await _crud_callback(ctx, "r", async (model, _uinfo) => {
137
158
  const params = query_string_to_json(ctx.request.url)
138
159
  // TODO : handle transactions
139
- const options= {transaction: undefined}
160
+ const options = { transaction: undefined }
140
161
  const data = await model.distinct(params.distinct_field, params, options)
141
162
  return data
142
163
  })
143
164
  }
144
-
165
+
145
166
  const route_save = async (ctx) => {
146
- await _crud_callback(ctx, 'w', async (model, uinfo) => {
167
+ await _crud_callback(ctx, "w", async (model, uinfo) => {
147
168
  const params = ctx.request.body
148
169
  if (uinfo?.fieldNames?.created_by) {
149
170
  params[uinfo.fieldNames.created_by] = uinfo.uid
150
171
  }
151
172
  // TODO : handle transactions
152
- const options= {transaction: undefined}
173
+ const options = { transaction: undefined }
153
174
  const data = await model.insert(params, options)
154
175
  return data
155
176
  })
156
177
  }
157
-
178
+
158
179
  const route_update = async (ctx) => {
159
- await _crud_callback(ctx, 'w', async (model, uinfo) => {
180
+ await _crud_callback(ctx, "w", async (model, uinfo) => {
160
181
  const params = ctx.request.body
161
182
  if (uinfo?.fieldNames?.last_update_by) {
162
183
  params[uinfo.fieldNames.last_update_by] = uinfo.uid
163
184
  }
164
185
  // TODO : handle transactions
165
- const options= {transaction: undefined}
166
- const data = await model.update(params, {id: params.id}, options)
186
+ const options = { transaction: undefined }
187
+ const data = await model.update(params, { id: params.id }, options)
167
188
  return data
168
189
  })
169
190
  }
170
-
191
+
171
192
  const route_delete = async (ctx) => {
172
- await _crud_callback(ctx, 'w', async (model, _uinfo) => {
193
+ await _crud_callback(ctx, "w", async (model, _uinfo) => {
173
194
  const params = ctx.request.body
174
195
  // TODO : handle transactions
175
- const options= {transaction: undefined}
176
- const data = await model.delete({id: params.id}, options)
196
+ const options = { transaction: undefined }
197
+ const data = await model.delete({ id: params.id }, options)
177
198
  return data
178
199
  })
179
200
  }
180
201
 
181
- let url = (!prefix)
182
- ? `/${route.url}`
183
- : `/${prefix}/${route.url}`
184
-
185
- while (url.indexOf('//')>=0) {
186
- url= url.replace(/\/\//g, "/")
202
+ let url = !prefix ? `/${route.url}` : `/${prefix}/${route.url}`
203
+
204
+ while (url.indexOf("//") >= 0) {
205
+ url = url.replace(/\/\//g, "/")
187
206
  }
188
207
 
189
208
  logger.debug(`[router] Routing table ${route.name} to ${url}`)
190
209
 
191
- const allowRead = route.mode.indexOf('r')>=0
192
- const allowDelete = route.mode.indexOf('w')>=0
193
- const allowUpsave = (route.mode.indexOf('u')>=0) || allowDelete
194
-
210
+ const allowRead = route.mode.indexOf("r") >= 0
211
+ const allowDelete = route.mode.indexOf("w") >= 0
212
+ const allowUpsave = route.mode.indexOf("u") >= 0 || allowDelete
213
+
195
214
  if (allowRead) {
196
- router.get (`${url}/find` , (ctx) => route_find(ctx))
197
- router.get (`${url}/read` , (ctx) => route_read(ctx))
198
- router.get (`${url}/distinct` , (ctx) => route_distinct(ctx))
199
- router.get (`${url}/key_list` , (ctx) => route_key_list(ctx))
215
+ router.get(`${url}/find`, (ctx) => route_find(ctx))
216
+ router.get(`${url}/read`, (ctx) => route_read(ctx))
217
+ router.get(`${url}/distinct`, (ctx) => route_distinct(ctx))
218
+ router.get(`${url}/key_list`, (ctx) => route_key_list(ctx))
200
219
  }
201
220
 
202
221
  if (allowUpsave) {
203
- router.post(`${url}/save` , (ctx) => route_save(ctx))
204
- router.post(`${url}/update` , (ctx) => route_update(ctx))
222
+ router.post(`${url}/save`, (ctx) => route_save(ctx))
223
+ router.post(`${url}/update`, (ctx) => route_update(ctx))
205
224
  }
206
225
  if (allowDelete) {
207
- router.post(`${url}/delete` , (ctx) => route_delete(ctx))
226
+ router.post(`${url}/delete`, (ctx) => route_delete(ctx))
208
227
  }
209
228
  })
210
229
  })
211
-
212
230
  }
213
231
 
214
- export default attachCrudRoutes
232
+ export default attachCrudRoutes