miolo 3.0.0-beta.162 → 3.0.0-beta.164
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/package.json +2 -2
- package/template/.env +1 -1
- package/template/biome.json +1 -1
- package/template/package.json +4 -3
- package/template/src/cli/context/data/DataProvider.jsx +13 -12
- package/template/src/cli/layout/nav-last-todos.jsx +1 -6
- package/template/src/cli/pages/todos/context/TodosProvider.jsx +12 -7
- package/template/src/ns/models/Todo.mjs +3 -0
- package/template/src/server/db/io/todos/find.mjs +2 -6
- package/template/src/server/db/io/todos/read.mjs +48 -32
- package/template/src/server/miolo/ssr/loader.mjs +4 -4
- package/template/src/server/routes/index.mjs +2 -1
- package/template/src/server/routes/todos/read.mjs +17 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miolo",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.164",
|
|
4
4
|
"description": "all-in-one koa-based server",
|
|
5
5
|
"author": "Donato Lorenzo <donato@afialapis.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@vitejs/plugin-react": "^5.1.4",
|
|
64
64
|
"autoprefixer": "^10.4.27",
|
|
65
65
|
"cacheiro": "^0.5.0-beta.11",
|
|
66
|
-
"calustra": "^1.0.0-beta.
|
|
66
|
+
"calustra": "^1.0.0-beta.14",
|
|
67
67
|
"cron": "^4.4.0",
|
|
68
68
|
"deepmerge": "^4.3.1",
|
|
69
69
|
"diskspace": "^2.0.0",
|
package/template/.env
CHANGED
package/template/biome.json
CHANGED
package/template/package.json
CHANGED
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"intre": "^3.0.0-beta.4",
|
|
45
45
|
"joi": "^18.0.2",
|
|
46
46
|
"lucide-react": "^0.577.0",
|
|
47
|
-
"miolo-cli": "^3.0.0-beta.
|
|
47
|
+
"miolo-cli": "^3.0.0-beta.164",
|
|
48
48
|
"miolo-model": "file:../miolo-model",
|
|
49
|
-
"miolo-react": "^3.0.0-beta.
|
|
49
|
+
"miolo-react": "^3.0.0-beta.164",
|
|
50
50
|
"next-themes": "^0.4.6",
|
|
51
51
|
"radix-ui": "^1.4.3",
|
|
52
52
|
"react": "^19.2.4",
|
|
@@ -60,7 +60,8 @@
|
|
|
60
60
|
"tw-animate-css": "^1.4.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"
|
|
63
|
+
"@biomejs/biome": "2.4.6",
|
|
64
|
+
"miolo": "^3.0.0-beta.164",
|
|
64
65
|
"sass-embedded": "^1.97.3"
|
|
65
66
|
},
|
|
66
67
|
"overrides": {
|
|
@@ -4,17 +4,18 @@ import TodoList from "#ns/models/TodoList.mjs"
|
|
|
4
4
|
import DataContext from "./DataContext.jsx"
|
|
5
5
|
|
|
6
6
|
const DataProvider = ({ children }) => {
|
|
7
|
-
const [status, setStatus] = useState("loaded")
|
|
8
7
|
const [breads, setBreads] = useState([])
|
|
9
8
|
const { useSsrData } = useSessionContext()
|
|
10
9
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
10
|
+
const {
|
|
11
|
+
data: lastTodos,
|
|
12
|
+
refresh: refreshLastTodos,
|
|
13
|
+
ready
|
|
14
|
+
} = useSsrData("lastTodos", {
|
|
15
|
+
url: "/api/todo/list",
|
|
16
|
+
params: { options: { limit: 4 } },
|
|
17
|
+
model: TodoList,
|
|
18
|
+
modifier: (data) => data.sort((a, b) => b.created_at - a.created_at)
|
|
18
19
|
})
|
|
19
20
|
|
|
20
21
|
const setTitle = useCallback((title) => {
|
|
@@ -26,10 +27,10 @@ const DataProvider = ({ children }) => {
|
|
|
26
27
|
return (
|
|
27
28
|
<DataContext.Provider
|
|
28
29
|
value={{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
loading:
|
|
32
|
-
loaded:
|
|
30
|
+
lastTodos,
|
|
31
|
+
refreshLastTodos,
|
|
32
|
+
loading: !ready,
|
|
33
|
+
loaded: ready,
|
|
33
34
|
breads,
|
|
34
35
|
setBreads,
|
|
35
36
|
setTitle
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
import { Cable, ChartSpline, ChevronRight, HousePlug, Route, RouteOff } from "lucide-react"
|
|
3
|
-
import { useMemo } from "react"
|
|
4
3
|
import { Link } from "react-router"
|
|
5
4
|
|
|
6
5
|
import {
|
|
@@ -21,11 +20,7 @@ import {
|
|
|
21
20
|
import useDataContext from "#cli/context/data/useDataContext.mjs"
|
|
22
21
|
|
|
23
22
|
export function NavLastTodos() {
|
|
24
|
-
const {
|
|
25
|
-
|
|
26
|
-
const lastTodos = useMemo(() => {
|
|
27
|
-
return todos.sort((a, b) => b.created_at - a.created_at).slice(0, 5)
|
|
28
|
-
}, [todos])
|
|
23
|
+
const { lastTodos } = useDataContext()
|
|
29
24
|
|
|
30
25
|
return (
|
|
31
26
|
<SidebarGroup>
|
|
@@ -4,13 +4,18 @@ import TodoList from "#ns/models/TodoList.mjs"
|
|
|
4
4
|
import TodosContext from "./TodosContext.jsx"
|
|
5
5
|
|
|
6
6
|
const TodosProvider = ({ children }) => {
|
|
7
|
-
const [status, setStatus] = useState("loaded")
|
|
7
|
+
// const [status, setStatus] = useState("loaded")
|
|
8
8
|
const { useSsrData, fetcher, authenticated } = useSessionContext()
|
|
9
9
|
const [useCrud, setUseCrud] = useState(true)
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const {
|
|
12
|
+
data: todoList,
|
|
13
|
+
setData: setTodoList,
|
|
14
|
+
refresh: refreshTodoList,
|
|
15
|
+
ready
|
|
16
|
+
} = useSsrData("todos", {
|
|
12
17
|
loader: async (_context, fetcher) => {
|
|
13
|
-
setStatus("loading")
|
|
18
|
+
//setStatus("loading")
|
|
14
19
|
let data
|
|
15
20
|
if (useCrud) {
|
|
16
21
|
const res = await fetcher.read("/crud/todo")
|
|
@@ -18,7 +23,7 @@ const TodosProvider = ({ children }) => {
|
|
|
18
23
|
} else {
|
|
19
24
|
data = await fetcher.get("/api/todo/list")
|
|
20
25
|
}
|
|
21
|
-
setStatus("loaded")
|
|
26
|
+
//setStatus("loaded")
|
|
22
27
|
return new TodoList(data.sort((a, b) => b.created_at - a.created_at))
|
|
23
28
|
}
|
|
24
29
|
})
|
|
@@ -53,7 +58,7 @@ const TodosProvider = ({ children }) => {
|
|
|
53
58
|
async function toggleIt() {
|
|
54
59
|
const nTodoList = [...todoList]
|
|
55
60
|
const selectedTodoIndex = nTodoList.findIndex((item) => item.id === todoId)
|
|
56
|
-
nTodoList[selectedTodoIndex].
|
|
61
|
+
nTodoList[selectedTodoIndex].toggle()
|
|
57
62
|
|
|
58
63
|
setTodoList(nTodoList)
|
|
59
64
|
|
|
@@ -120,8 +125,8 @@ const TodosProvider = ({ children }) => {
|
|
|
120
125
|
value={{
|
|
121
126
|
todoList,
|
|
122
127
|
refreshTodoList,
|
|
123
|
-
loading:
|
|
124
|
-
loaded:
|
|
128
|
+
loading: !ready,
|
|
129
|
+
loaded: ready,
|
|
125
130
|
addTodo,
|
|
126
131
|
toggleTodo,
|
|
127
132
|
removeTodo,
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { db_todo_read } from "./read.mjs"
|
|
2
2
|
|
|
3
3
|
export async function db_todo_find(ctx, params) {
|
|
4
|
-
ctx.miolo.logger.verbose(`[db_todo_find] id: ${params?.id}`)
|
|
4
|
+
ctx.miolo.logger.verbose(`[db_todo_find] id: ${params?.filter?.id}`)
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
id: params.id
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const todos = await db_todo_read(ctx, filter)
|
|
6
|
+
const todos = await db_todo_read(ctx, params)
|
|
11
7
|
|
|
12
8
|
if (todos.length === 0) {
|
|
13
9
|
return null
|
|
@@ -9,44 +9,55 @@ import { bool_null, opt_int, opt_str_null } from "#server/utils/schema.mjs"
|
|
|
9
9
|
* description
|
|
10
10
|
* done
|
|
11
11
|
* }
|
|
12
|
+
* options {
|
|
13
|
+
* limit : optional int
|
|
14
|
+
* }
|
|
12
15
|
*/
|
|
13
|
-
async function _db_todo_read(ctx, filter) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
async function _db_todo_read(ctx, { filter, options }) {
|
|
17
|
+
try {
|
|
18
|
+
ctx.miolo.logger.verbose(
|
|
19
|
+
`[db_todo_read] Reading todos with filter: ${JSON.stringify(filter)} and options ${JSON.stringify(options)}`
|
|
20
|
+
)
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
// TODO : handle transactions
|
|
19
|
-
const options = { transaction: undefined }
|
|
22
|
+
const conn = await ctx.miolo.db.get_connection()
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
let query = `
|
|
25
|
+
SELECT *
|
|
26
|
+
FROM todo AS t
|
|
27
|
+
*WHERE*`
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
todo_id: { alias: "t.id" },
|
|
30
|
-
description: { op: "~*" },
|
|
31
|
-
done: { coalesce: false, alias: "COALESCE(done, false)" }
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
fields: ["id", "todo_id", "description", "done"]
|
|
29
|
+
if (options?.limit !== undefined) {
|
|
30
|
+
query += ` LIMIT ${options.limit}`
|
|
35
31
|
}
|
|
36
|
-
)
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
const [where, values] = make_query_filter(
|
|
34
|
+
filter,
|
|
35
|
+
{
|
|
36
|
+
todo_id: { alias: "t.id" },
|
|
37
|
+
description: { op: "~*" },
|
|
38
|
+
done: { coalesce: false, alias: "COALESCE(done, false)" }
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
fields: ["id", "todo_id", "description", "done"]
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
query = query.replace("*WHERE*", where)
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
// if (values.length == 0){
|
|
48
|
+
// ctx.miolo.logger.warn(`[prop_detail] Some filter must be specified`)
|
|
49
|
+
// return []
|
|
50
|
+
// }
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
const todos = await conn.select(query, values)
|
|
46
53
|
|
|
47
|
-
|
|
54
|
+
ctx.miolo.logger.verbose(`[db_todo_read] Read ${todos.length} todos`)
|
|
48
55
|
|
|
49
|
-
|
|
56
|
+
return todos
|
|
57
|
+
} catch (error) {
|
|
58
|
+
ctx.miolo.logger.error(`[db_todo_read] Error reading todos: ${error}`)
|
|
59
|
+
return []
|
|
60
|
+
}
|
|
50
61
|
}
|
|
51
62
|
|
|
52
63
|
/**
|
|
@@ -58,10 +69,15 @@ async function _db_todo_read(ctx, filter) {
|
|
|
58
69
|
*/
|
|
59
70
|
|
|
60
71
|
const todo_read_schema = Joi.object({
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
filter: Joi.object({
|
|
73
|
+
id: opt_int,
|
|
74
|
+
todo_id: opt_int,
|
|
75
|
+
description: opt_str_null,
|
|
76
|
+
done: bool_null
|
|
77
|
+
}),
|
|
78
|
+
options: Joi.object({
|
|
79
|
+
limit: opt_int
|
|
80
|
+
})
|
|
65
81
|
})
|
|
66
82
|
|
|
67
83
|
export const db_todo_read = with_miolo_schema(_db_todo_read, todo_read_schema)
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { db_todo_read } from "#server/db/io/todos/read.mjs"
|
|
2
2
|
|
|
3
3
|
const loader = async (ctx) => {
|
|
4
|
-
let
|
|
4
|
+
let lastTodos = []
|
|
5
5
|
|
|
6
6
|
try {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
lastTodos = await db_todo_read(ctx, { options: { limit: 3 } })
|
|
8
|
+
lastTodos = lastTodos.sort((a, b) => b.created_at - a.created_at)
|
|
9
9
|
} catch (_) {}
|
|
10
10
|
|
|
11
11
|
const data = {
|
|
12
|
-
|
|
12
|
+
lastTodos
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
return data
|
|
@@ -2,7 +2,7 @@ import Joi from "joi"
|
|
|
2
2
|
import { with_miolo_schema } from "miolo"
|
|
3
3
|
import { r_todo_delete, r_todo_toggle_done, r_todo_upsave } from "./todos/mod.mjs"
|
|
4
4
|
|
|
5
|
-
import { r_todo_find, r_todo_list } from "./todos/read.mjs"
|
|
5
|
+
import { r_todo_find, r_todo_last, r_todo_list } from "./todos/read.mjs"
|
|
6
6
|
import { r_todo_count_last_hours, r_todo_insert_fake } from "./todos/special.mjs"
|
|
7
7
|
import { r_change_password, r_forgot, r_user_save } from "./users/user.mjs"
|
|
8
8
|
|
|
@@ -21,6 +21,7 @@ export default [
|
|
|
21
21
|
{ method: "POST", url: "/user/save", auth, callback: r_user_save },
|
|
22
22
|
|
|
23
23
|
{ method: "GET", url: "/todo/list", auth, callback: r_todo_list },
|
|
24
|
+
{ method: "GET", url: "/todo/last", auth, callback: r_todo_last },
|
|
24
25
|
{ method: "GET", url: "/todo/findone", auth, callback: r_todo_find },
|
|
25
26
|
{ method: "POST", url: "/todo/upsave", auth, callback: r_todo_upsave },
|
|
26
27
|
{ method: "POST", url: "/todo/delete", auth, callback: r_todo_delete },
|
|
@@ -2,15 +2,12 @@ import { db_todo_find } from "#server/db/io/todos/find.mjs"
|
|
|
2
2
|
import { db_todo_read } from "#server/db/io/todos/read.mjs"
|
|
3
3
|
|
|
4
4
|
export async function r_todo_list(ctx, params) {
|
|
5
|
-
// const _p = ctx.miolo.parser
|
|
6
|
-
// TODO Use some filtering here, or caching
|
|
7
|
-
|
|
8
5
|
try {
|
|
9
6
|
ctx.miolo.logger.info(`[r_todo_list] Reading todo list`)
|
|
10
7
|
|
|
11
|
-
const res = await db_todo_read(ctx
|
|
8
|
+
const res = await db_todo_read(ctx, params)
|
|
12
9
|
|
|
13
|
-
ctx.miolo.logger.info(`[r_todo_list] Read todo list`)
|
|
10
|
+
ctx.miolo.logger.info(`[r_todo_list] Read todo list (${res.length})`)
|
|
14
11
|
return { ok: true, data: res }
|
|
15
12
|
} catch (error) {
|
|
16
13
|
ctx.miolo.logger.error(`[r_todo_list] Error reading todo list: ${error}`)
|
|
@@ -18,11 +15,25 @@ export async function r_todo_list(ctx, params) {
|
|
|
18
15
|
}
|
|
19
16
|
}
|
|
20
17
|
|
|
18
|
+
export async function r_todo_last(ctx, params) {
|
|
19
|
+
try {
|
|
20
|
+
ctx.miolo.logger.info(`[r_todo_last] Reading last todos`)
|
|
21
|
+
|
|
22
|
+
const res = await db_todo_read(ctx, { options: { limit: 3 } })
|
|
23
|
+
|
|
24
|
+
ctx.miolo.logger.info(`[r_todo_last] Read last todos (${res.length})`)
|
|
25
|
+
return { ok: true, data: res }
|
|
26
|
+
} catch (error) {
|
|
27
|
+
ctx.miolo.logger.error(`[r_todo_last] Error reading last todos: ${error}`)
|
|
28
|
+
return { ok: false, error: error?.message }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
21
32
|
export async function r_todo_find(ctx, params) {
|
|
22
33
|
try {
|
|
23
34
|
ctx.miolo.logger.info(`[r_todo_find] Reading todo for tid ${params?.id}`)
|
|
24
35
|
|
|
25
|
-
const todo = await db_todo_find(ctx
|
|
36
|
+
const todo = await db_todo_find(ctx, { filter: { id: params?.id } })
|
|
26
37
|
|
|
27
38
|
ctx.miolo.logger.info(`[r_todo_find] Read todo for tid ${params?.id}`)
|
|
28
39
|
return { ok: todo?.id !== undefined, data: todo }
|