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.
- package/bin/build/build.mjs +53 -0
- package/bin/build/build_bin.mjs +17 -0
- package/bin/build/cli/client.mjs +52 -0
- package/bin/build/cli/css.mjs +22 -0
- package/bin/build/cli/index.mjs +40 -0
- package/bin/build/cli/ssr.mjs +21 -0
- package/bin/build/server/aliases.mjs +112 -0
- package/bin/build/server/babel.config.js +24 -0
- package/bin/build/server/banner.mjs +20 -0
- package/bin/build/server/bundle.mjs +111 -0
- package/bin/build/server/fix.mjs +15 -0
- package/bin/build/server/index.mjs +69 -0
- package/bin/build/server/options.mjs +83 -0
- package/bin/create/auth.mjs +23 -0
- package/bin/create/copy.mjs +175 -0
- package/bin/create/docker.mjs +25 -0
- package/bin/create/index.mjs +137 -0
- package/bin/create/pkgjson.mjs +72 -0
- package/bin/create/prepare-template.mjs +158 -0
- package/bin/create/validation.mjs +27 -0
- package/bin/dev/dev.mjs +32 -23
- package/bin/dev/dev_start.mjs +6 -5
- package/bin/index.mjs +94 -52
- package/bin/prod-bin/create-bin.mjs +42 -27
- package/bin/prod-bin/run.mjs +13 -9
- package/bin/{prod-run → run}/pid.mjs +4 -4
- package/bin/run/restart.mjs +13 -0
- package/bin/run/start.mjs +18 -0
- package/bin/run/stop.mjs +20 -0
- package/bin/util.mjs +35 -11
- package/package.json +59 -39
- package/src/config/.env +34 -12
- package/src/config/defaults.mjs +253 -185
- package/src/config/env.mjs +40 -22
- package/src/config/index.mjs +19 -24
- package/src/config/util.mjs +25 -10
- package/src/db-conn.mjs +34 -0
- package/src/engines/cron/emails.mjs +10 -5
- package/src/engines/cron/index.mjs +45 -51
- package/src/engines/cron/init.mjs +16 -17
- package/src/engines/cron/ipsum.mjs +65 -60
- package/src/engines/cron/syscheck.mjs +30 -30
- package/src/engines/emailer/index.mjs +1 -2
- package/src/engines/emailer/queue.mjs +14 -20
- package/src/engines/emailer/transporter.mjs +86 -74
- package/src/engines/geoip/index.mjs +23 -28
- package/src/engines/http/index.mjs +26 -15
- package/src/engines/logger/buildErrorEmailBody.mjs +72 -0
- package/src/engines/logger/index.mjs +114 -122
- package/src/engines/logger/injectStackTrace.mjs +59 -0
- package/src/engines/logger/logger_mail.mjs +47 -61
- package/src/engines/logger/reopenTransportOnHupSignal.mjs +12 -13
- package/src/engines/parser/Parser.mjs +77 -60
- package/src/engines/parser/index.mjs +1 -1
- package/src/engines/schema/diffObjs.mjs +41 -0
- package/src/engines/schema/index.mjs +4 -0
- package/src/engines/schema/input.mjs +54 -0
- package/src/engines/schema/output.mjs +66 -0
- package/src/engines/socket/index.mjs +44 -46
- package/src/index.mjs +15 -10
- package/src/middleware/auth/basic.mjs +41 -40
- package/src/middleware/auth/custom.mjs +10 -13
- package/src/middleware/auth/guest.mjs +27 -27
- package/src/middleware/auth/passport/index.mjs +374 -0
- package/src/middleware/auth/passport/session/index.mjs +43 -0
- package/src/middleware/auth/{credentials → passport}/session/store.mjs +35 -15
- package/src/middleware/auth/passport/session/store_koa_redis.mjs +3 -0
- package/src/middleware/context/cache/index.mjs +78 -33
- package/src/middleware/context/cache/options.mjs +19 -21
- package/src/middleware/context/db.mjs +45 -20
- package/src/middleware/context/index.mjs +12 -12
- package/src/middleware/extra.mjs +4 -5
- package/src/middleware/http/body.mjs +25 -25
- package/src/middleware/http/catcher.mjs +81 -8
- package/src/middleware/http/custom_blacklist.mjs +19 -16
- package/src/middleware/http/headers.mjs +37 -34
- package/src/middleware/http/ratelimit.mjs +16 -23
- package/src/middleware/http/request.mjs +60 -65
- package/src/middleware/routes/catch_js_error.mjs +30 -23
- package/src/middleware/routes/robots.mjs +4 -7
- package/src/middleware/routes/router/crud/attachCrudRoutes.mjs +108 -90
- package/src/middleware/routes/router/crud/getCrudConfig.mjs +31 -55
- package/src/middleware/routes/router/defaults.mjs +6 -19
- package/src/middleware/routes/router/index.mjs +17 -21
- package/src/middleware/routes/router/queries/attachQueriesRoutes.mjs +227 -50
- package/src/middleware/routes/router/queries/getQueriesConfig.mjs +45 -55
- package/src/middleware/routes/router/utils.mjs +41 -26
- package/src/middleware/ssr/context.mjs +5 -7
- package/src/middleware/ssr/html.mjs +66 -43
- package/src/middleware/ssr/loader.mjs +11 -14
- package/src/middleware/ssr/ssr_render.mjs +39 -22
- package/src/middleware/static/index.mjs +33 -14
- package/src/middleware/vite/devserver.mjs +38 -22
- package/src/middleware/vite/watcher.mjs +12 -14
- package/src/server-cron.mjs +13 -8
- package/src/server-dev.mjs +13 -16
- package/src/server.mjs +49 -51
- package/template/.agent/skills/miolo-app-arch/SKILL.md +218 -0
- package/template/.agent/skills/miolo-auth/SKILL.md +450 -0
- package/template/.agent/skills/miolo-cli-router/SKILL.md +394 -0
- package/template/.agent/skills/miolo-database/SKILL.md +358 -0
- package/template/.agent/skills/miolo-react-patterns/SKILL.md +426 -0
- package/template/.agent/skills/miolo-routing/SKILL.md +326 -0
- package/template/.agent/skills/miolo-schemas/SKILL.md +329 -0
- package/template/.agent/skills/miolo-session-context/SKILL.md +397 -0
- package/template/.agent/skills/miolo-ssr/SKILL.md +433 -0
- package/template/.editorconfig +18 -0
- package/template/.env +120 -0
- package/template/biome.json +63 -0
- package/template/components.json +21 -0
- package/template/db/init.sh +89 -0
- package/template/db/sql/00_drop.sql +2 -0
- package/template/db/sql/01_users.sql +31 -0
- package/template/db/sql/02_todos.sql +20 -0
- package/template/docker/Dockerfile +13 -0
- package/template/docker/docker-compose.yaml +79 -0
- package/template/gitignore +42 -0
- package/template/jsconfig.json +18 -0
- package/template/package.json +88 -0
- package/template/postcss.config.js +9 -0
- package/template/src/cli/App.jsx +25 -0
- package/template/src/cli/components/JsonTreeViewer.jsx +128 -0
- package/template/src/cli/components/shadcn-io/spinner/index.jsx +232 -0
- package/template/src/cli/components/stepper.jsx +408 -0
- package/template/src/cli/components/ui/avatar.jsx +36 -0
- package/template/src/cli/components/ui/badge.jsx +31 -0
- package/template/src/cli/components/ui/breadcrumb.jsx +97 -0
- package/template/src/cli/components/ui/card.jsx +73 -0
- package/template/src/cli/components/ui/collapsible.jsx +16 -0
- package/template/src/cli/components/ui/dropdown-menu.jsx +179 -0
- package/template/src/cli/components/ui/field.jsx +217 -0
- package/template/src/cli/components/ui/input.jsx +19 -0
- package/template/src/cli/components/ui/label.jsx +17 -0
- package/template/src/cli/components/ui/pagination.jsx +99 -0
- package/template/src/cli/components/ui/patched/alert.jsx +56 -0
- package/template/src/cli/components/ui/patched/button.jsx +45 -0
- package/template/src/cli/components/ui/patched/dialog.jsx +114 -0
- package/template/src/cli/components/ui/patched/sidebar.jsx +660 -0
- package/template/src/cli/components/ui/select.jsx +141 -0
- package/template/src/cli/components/ui/separator.jsx +21 -0
- package/template/src/cli/components/ui/sheet.jsx +115 -0
- package/template/src/cli/components/ui/skeleton.jsx +13 -0
- package/template/src/cli/components/ui/sonner.jsx +22 -0
- package/template/src/cli/components/ui/switch.jsx +25 -0
- package/template/src/cli/components/ui/table.jsx +88 -0
- package/template/src/cli/components/ui/textarea.jsx +16 -0
- package/template/src/cli/components/ui/tooltip.jsx +45 -0
- package/template/src/cli/config/store_keys.mjs +2 -0
- package/template/src/cli/context/data/DataContext.jsx +5 -0
- package/template/src/cli/context/data/DataProvider.jsx +44 -0
- package/template/src/cli/context/data/useBreads.mjs +15 -0
- package/template/src/cli/context/data/useDataContext.mjs +4 -0
- package/template/src/cli/context/session/SessionContext.mjs +4 -0
- package/template/src/cli/context/session/SessionProvider.jsx +31 -0
- package/template/src/cli/context/session/makePermissioner.mjs +34 -0
- package/template/src/cli/context/session/useSessionContext.mjs +6 -0
- package/template/src/cli/context/theme/ThemeContext.mjs +4 -0
- package/template/src/cli/context/theme/ThemeProvider.jsx +49 -0
- package/template/src/cli/context/theme/useThemeContext.mjs +6 -0
- package/template/src/cli/context/ui/UIContext.jsx +5 -0
- package/template/src/cli/context/ui/UIProvider.jsx +16 -0
- package/template/src/cli/context/ui/useUIContext.mjs +4 -0
- package/template/src/cli/context/util.mjs +17 -0
- package/template/src/cli/entry-cli.jsx +33 -0
- package/template/src/cli/hooks/useIsMobile.mjs +19 -0
- package/template/src/cli/hooks/useStoragedState.mjs +63 -0
- package/template/src/cli/index.html +29 -0
- package/template/src/cli/layout/app-sidebar.jsx +25 -0
- package/template/src/cli/layout/main-layout.jsx +63 -0
- package/template/src/cli/layout/nav-last-todos.jsx +72 -0
- package/template/src/cli/layout/nav-main.jsx +39 -0
- package/template/src/cli/layout/nav-user.jsx +105 -0
- package/template/src/cli/layout/prop-switcher.jsx +93 -0
- package/template/src/cli/lib/utils.mjs +10 -0
- package/template/src/cli/pages/Index.jsx +13 -0
- package/template/src/cli/pages/IndexOffline.jsx +13 -0
- package/template/src/cli/pages/IndexOnline.jsx +18 -0
- package/template/src/cli/pages/dash/Dashboard.jsx +29 -0
- package/template/src/cli/pages/offline/Login.jsx +43 -0
- package/template/src/cli/pages/offline/LoginForm.jsx +115 -0
- package/template/src/cli/pages/security/Security.jsx +39 -0
- package/template/src/cli/pages/security/SecurityForm.jsx +106 -0
- package/template/src/cli/pages/todos/TodoActions.jsx +99 -0
- package/template/src/cli/pages/todos/TodoAdd.jsx +43 -0
- package/template/src/cli/pages/todos/TodoList.jsx +60 -0
- package/template/src/cli/pages/todos/Todos.jsx +23 -0
- package/template/src/cli/pages/todos/context/TodosContext.jsx +5 -0
- package/template/src/cli/pages/todos/context/TodosProvider.jsx +191 -0
- package/template/src/cli/pages/todos/context/useTodosContext.mjs +4 -0
- package/template/src/ns/models/Todo.mjs +29 -0
- package/template/src/ns/models/TodoList.mjs +8 -0
- package/template/src/ns/models/User.mjs +40 -0
- package/template/src/server/bot/check_today.mjs +10 -0
- package/template/src/server/io/cache/base.mjs +21 -0
- package/template/src/server/io/db/filter.mjs +92 -0
- package/template/src/server/io/db/todos/delete.mjs +29 -0
- package/template/src/server/io/db/todos/find.mjs +13 -0
- package/template/src/server/io/db/todos/read.mjs +83 -0
- package/template/src/server/io/db/todos/toggle.mjs +37 -0
- package/template/src/server/io/db/todos/upsave.mjs +32 -0
- package/template/src/server/io/db/triggers/user.mjs +13 -0
- package/template/src/server/io/db/users/auth.mjs +132 -0
- package/template/src/server/io/db/users/pwd.mjs +38 -0
- package/template/src/server/io/db/users/save.mjs +17 -0
- package/template/src/server/miolo/auth/basic.mjs +15 -0
- package/template/src/server/miolo/auth/guest.mjs +3 -0
- package/template/src/server/miolo/auth/passport.mjs +73 -0
- package/template/src/server/miolo/cache.mjs +11 -0
- package/template/src/server/miolo/cron/foo.mjs +7 -0
- package/template/src/server/miolo/cron/index.mjs +28 -0
- package/template/src/server/miolo/cron/invalidate.mjs +21 -0
- package/template/src/server/miolo/db.mjs +36 -0
- package/template/src/server/miolo/http.mjs +14 -0
- package/template/src/server/miolo/index.mjs +43 -0
- package/template/src/server/miolo/routes/crud.mjs +16 -0
- package/template/src/server/miolo/routes/index.mjs +8 -0
- package/template/src/server/miolo/ssr/entry-server.jsx +13 -0
- package/template/src/server/miolo/ssr/loader.mjs +18 -0
- package/template/src/server/routes/index.mjs +66 -0
- package/template/src/server/routes/todos/mod.mjs +52 -0
- package/template/src/server/routes/todos/read.mjs +45 -0
- package/template/src/server/routes/todos/special.mjs +47 -0
- package/template/src/server/routes/users/user.mjs +54 -0
- package/template/src/server/server.mjs +10 -0
- package/template/src/server/utils/crypt.mjs +38 -0
- package/template/src/server/utils/io.mjs +15 -0
- package/template/src/server/utils/pwdfor.mjs +25 -0
- package/template/src/server/utils/schema.mjs +22 -0
- package/template/src/static/img/default/profile.png +0 -0
- package/template/src/static/img/favicon.ico +0 -0
- package/template/src/static/img/miolo_logo.png +0 -0
- package/template/src/static/img/miolo_name.png +0 -0
- package/template/src/static/public/manifest.json +21 -0
- package/template/src/static/public/sw.js +79 -0
- package/template/src/static/style/globals.css +156 -0
- package/template/src/static/style/json-tree.css +54 -0
- package/template/src/static/style/skeleton.css +49 -0
- package/bin/prod-build/build-client.mjs +0 -67
- package/bin/prod-build/build-server.mjs +0 -58
- package/bin/prod-run/restart.mjs +0 -9
- package/bin/prod-run/start.mjs +0 -15
- package/bin/prod-run/stop.mjs +0 -20
- package/src/engines/logger/verify.mjs +0 -22
- package/src/middleware/auth/credentials/index.mjs +0 -151
- package/src/middleware/auth/credentials/session/index.mjs +0 -24
- package/src/middleware/auth/credentials/session/store_koa_redis.mjs +0 -3
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
import { performance } from
|
|
2
|
-
import { cyan, green,
|
|
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
|
|
4
|
+
import { geoip_localize_ip } from "../../engines/geoip/index.mjs"
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const REQUEST_COUNTER = {
|
|
7
7
|
total: 0
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
function _validate_ip(ipaddress) {
|
|
11
|
-
if (
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
?
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
?
|
|
78
|
-
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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(
|
|
117
|
-
|
|
118
|
-
const tcolor= elapsed < reqConfig.lazy
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
|
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
|
|
2
|
-
import
|
|
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
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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 = {
|
|
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
|
|
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(
|
|
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
|
|
2
|
-
|
|
1
|
+
import { query_string_to_json } from "../utils.mjs"
|
|
3
2
|
|
|
4
3
|
function attachCrudRoutes(router, crudConfigs, logger) {
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
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=
|
|
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
|
|
32
|
-
ctx.miolo.logger.error(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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 (!
|
|
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
|
|
62
|
+
let data = {}
|
|
61
63
|
try {
|
|
62
64
|
const authenticated = await _crud_auth_callback(ctx, op)
|
|
63
65
|
|
|
64
|
-
if (!
|
|
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
|
-
|
|
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 (!
|
|
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
|
-
|
|
91
|
-
|
|
106
|
+
|
|
107
|
+
data = await callback(model, uinfo)
|
|
108
|
+
|
|
92
109
|
if (route?.after) {
|
|
93
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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 =
|
|
182
|
-
|
|
183
|
-
|
|
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(
|
|
192
|
-
const allowDelete = route.mode.indexOf(
|
|
193
|
-
const allowUpsave =
|
|
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
|
|
197
|
-
router.get
|
|
198
|
-
router.get
|
|
199
|
-
router.get
|
|
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
|
|
204
|
-
router.post(`${url}/update
|
|
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
|
|
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
|