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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miolo",
3
- "version": "3.0.0-beta.162",
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.13",
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
@@ -58,7 +58,7 @@ MIOLO_DB_POOL_IDLE_TIMEOUT_MS=10000
58
58
  # Logging
59
59
  #
60
60
 
61
- MIOLO_LOG_LEVEL=debug
61
+ MIOLO_LOG_LEVEL=info
62
62
  MIOLO_LOG_CONSOLE_ENABLED=true
63
63
  MIOLO_LOG_FILE_ENABLED=false
64
64
  MIOLO_LOG_MAIL_ENABLED=false
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.4.5/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.4.6/schema.json",
3
3
  "files": {
4
4
  "includes": [
5
5
  "**/*",
@@ -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.162",
47
+ "miolo-cli": "^3.0.0-beta.164",
48
48
  "miolo-model": "file:../miolo-model",
49
- "miolo-react": "^3.0.0-beta.162",
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
- "miolo": "^3.0.0-beta.162",
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 [todos, _setTodos, refreshTodos] = useSsrData("todos", {
12
- loader: async (_context, fetcher) => {
13
- setStatus("loading")
14
- const { data: nTodos } = await fetcher.get("/api/todo/list")
15
- setStatus("loaded")
16
- return new TodoList(nTodos)
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
- todos,
30
- refreshTodos,
31
- loading: status !== "loaded",
32
- loaded: status === "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 { todos } = useDataContext()
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 [todoList, setTodoList, refreshTodoList] = useSsrData("todos", {
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].done = !nTodoList[selectedTodoIndex].done
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: status !== "loaded",
124
- loaded: status === "loaded",
128
+ loading: !ready,
129
+ loaded: ready,
125
130
  addTodo,
126
131
  toggleTodo,
127
132
  removeTodo,
@@ -10,6 +10,9 @@ export default class Todo extends MioloModel {
10
10
  get done() {
11
11
  return this._get("done", false)
12
12
  }
13
+ toggle() {
14
+ this._set("done", !this.done)
15
+ }
13
16
 
14
17
  get createdAt() {
15
18
  return this._get("created_at")
@@ -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 filter = {
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
- ctx.miolo.logger.verbose(`[db_todo_read] Reading todos...`)
15
- ctx.miolo.logger.silly(`[db_todo_read] filter: ${JSON.stringify(filter)}`)
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
- const conn = await ctx.miolo.db.get_connection()
18
- // TODO : handle transactions
19
- const options = { transaction: undefined }
22
+ const conn = await ctx.miolo.db.get_connection()
20
23
 
21
- let query = `
22
- SELECT *
23
- FROM todo AS t
24
- *WHERE*`
24
+ let query = `
25
+ SELECT *
26
+ FROM todo AS t
27
+ *WHERE*`
25
28
 
26
- const [where, values] = make_query_filter(
27
- filter,
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
- query = query.replace("*WHERE*", where)
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
- // if (values.length == 0){
41
- // ctx.miolo.logger.warn(`[prop_detail] Some filter must be specified`)
42
- // return []
43
- // }
47
+ // if (values.length == 0){
48
+ // ctx.miolo.logger.warn(`[prop_detail] Some filter must be specified`)
49
+ // return []
50
+ // }
44
51
 
45
- const todos = await conn.select(query, values, options)
52
+ const todos = await conn.select(query, values)
46
53
 
47
- ctx.miolo.logger.verbose(`[db_todo_read] Read ${todos.length} todos`)
54
+ ctx.miolo.logger.verbose(`[db_todo_read] Read ${todos.length} todos`)
48
55
 
49
- return todos
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
- id: opt_int,
62
- todo_id: opt_int,
63
- description: opt_str_null,
64
- done: bool_null
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 todos = []
4
+ let lastTodos = []
5
5
 
6
6
  try {
7
- todos = await db_todo_read(ctx, {})
8
- todos = todos.sort((a, b) => b.created_at - a.created_at)
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
- todos
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.miolo, params)
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.miolo, params)
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 }