miolo 3.0.0-beta.150 → 3.0.0-beta.152

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.
@@ -153,8 +153,8 @@ export function copyTemplate(sourcePath, destPath, appName, options = {}) {
153
153
  fs.copyFileSync(srcPath, destItemPath)
154
154
  }
155
155
  } else if (stat.isDirectory()) {
156
- // Only copy src/ and docker/ directories
157
- if (item === 'src' || item === 'docker') {
156
+ // Only copy src/, db/ and docker/ directories
157
+ if (item === 'src' || item === 'docker'|| item === 'db') {
158
158
  copyDirectory(srcPath, destItemPath, appName, options)
159
159
  }
160
160
  }
@@ -100,6 +100,35 @@ export default async function create(appName, options = {}) {
100
100
  console.warn('[miolo] Please run "npm install" manually in the project directory')
101
101
  }
102
102
 
103
+ // Initialize database
104
+ const dbInitScript = path.join(destPath, 'db/init.sh')
105
+ if (fs.existsSync(dbInitScript)) {
106
+ console.log('')
107
+ console.log('[miolo] Database initialization')
108
+ console.log('[miolo] ⚠️ Note: This step may require sudo password if your user doesn\'t have CREATEDB permission')
109
+ console.log('[miolo] Database name will be:', appName)
110
+
111
+ // Make script executable
112
+ try {
113
+ fs.chmodSync(dbInitScript, 0o755)
114
+ } catch (_error) {
115
+ // Ignore chmod errors
116
+ }
117
+
118
+ try {
119
+ execSync(`${dbInitScript} ${appName}`, {
120
+ cwd: destPath,
121
+ stdio: 'inherit'
122
+ })
123
+ console.log('[miolo] ✅ Database initialized successfully')
124
+ } catch (_error) {
125
+ console.warn('[miolo] ⚠️ Warning: Database initialization failed or was skipped')
126
+ console.warn('[miolo] You can initialize it manually later by running:')
127
+ console.warn(`[miolo] cd ${dest} && ./db/init.sh ${appName}`)
128
+ }
129
+ }
130
+
131
+ console.log('')
103
132
  console.log('[miolo] ✅ App created successfully!')
104
133
  console.log('[miolo] To get started:')
105
134
  console.log(` cd ${dest}`)
@@ -43,7 +43,7 @@ const filesToCopy = [
43
43
  { src: 'package.json', dest: 'package.json' },
44
44
  { src: 'eslint.config.js', dest: 'eslint.config.js' },
45
45
  { src: 'postcss.config.js', dest: 'postcss.config.js' },
46
- { src: 'vite.config.mjs', dest: 'vite.config.mjs' }
46
+ //{ src: 'vite.config.mjs', dest: 'vite.config.mjs' }
47
47
  ]
48
48
 
49
49
  // Copy individual files
@@ -60,7 +60,7 @@ for (const { src, dest } of filesToCopy) {
60
60
  }
61
61
 
62
62
  // Copy directories
63
- const dirsToCopy = ['src', 'docker']
63
+ const dirsToCopy = ['src', 'docker', 'db']
64
64
 
65
65
  for (const dir of dirsToCopy) {
66
66
  const srcDir = path.join(mioloSamplePath, dir)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miolo",
3
- "version": "3.0.0-beta.150",
3
+ "version": "3.0.0-beta.152",
4
4
  "description": "all-in-one koa-based server",
5
5
  "author": "Donato Lorenzo <donato@afialapis.com>",
6
6
  "contributors": [
package/src/server.mjs CHANGED
@@ -10,12 +10,12 @@ import { init_rate_limit_middleware } from './middleware/http/ratelimit.mjs
10
10
  import { init_static_middleware } from './middleware/static/index.mjs'
11
11
  import { init_request_middleware } from './middleware/http/request.mjs'
12
12
  import { init_route_robots } from './middleware/routes/robots.mjs'
13
- import { init_route_catch_js_error} from './middleware/routes/catch_js_error.mjs'
13
+ import { init_route_catch_js_error } from './middleware/routes/catch_js_error.mjs'
14
14
 
15
- import {init_guest_auth_middleware} from'./middleware/auth/guest.mjs'
16
- import {init_basic_auth_middleware} from'./middleware/auth/basic.mjs'
17
- import {init_credentials_auth_middleware} from'./middleware/auth/credentials/index.mjs'
18
- import {init_custom_auth_middleware} from'./middleware/auth/custom.mjs'
15
+ import { init_guest_auth_middleware } from './middleware/auth/guest.mjs'
16
+ import { init_basic_auth_middleware } from './middleware/auth/basic.mjs'
17
+ import { init_credentials_auth_middleware }from './middleware/auth/credentials/index.mjs'
18
+ import { init_custom_auth_middleware } from './middleware/auth/custom.mjs'
19
19
 
20
20
  import { init_extra_middlewares } from './middleware/extra.mjs'
21
21
  import { init_router } from './middleware/routes/router/index.mjs'
package/template/.env CHANGED
@@ -1,12 +1,14 @@
1
1
  #
2
- # miolo
2
+ # General
3
3
  #
4
+
4
5
  MIOLO_NAME=miolo-sample
5
6
  MIOLO_INTRE_LOCALE=es
6
7
 
7
8
  #
8
9
  # HTTP
9
10
  #
11
+
10
12
  MIOLO_PORT=8001
11
13
  MIOLO_HOSTNAME=localhost
12
14
  MIOLO_HOSTNAME_DOCKER=0.0.0.0
@@ -19,46 +21,47 @@ MIOLO_REQUEST_SLOW=4 # seconds to consider slow a request
19
21
  MIOLO_GEOIP_ENABLED=true
20
22
  MIOLO_GEOIP_LOCAL_IPS=127.0.0.1,172.22.0.1,172.19.0.1
21
23
 
22
-
23
24
  #
24
25
  # Session
25
26
  #
26
- MIOLO_SESSION_SALT=33dd1f72-02a7-4d56-9d17-3aafacd1e0ca
27
- MIOLO_SESSION_SECRET=bfc5abbd-38dc-4d1f-bfcc-35771567083c
27
+
28
+ MIOLO_SESSION_SALT=00000000-0000-0000-0000-000000000000
29
+ MIOLO_SESSION_SECRET=00000000-0000-0000-0000-000000000000
28
30
  MIOLO_SESSION_MAX_AGE=864000000
29
31
  MIOLO_SESSION_SECURE=false
30
32
  MIOLO_SESSION_RENEW=true
31
33
  MIOLO_SESSION_SAME_SITE=strict # lax | strict
32
34
 
33
-
34
35
  #
35
36
  # Database
36
37
  #
38
+
37
39
  MIOLO_DB_DIALECT=postgres
38
- MIOLO_DB_DATABASE=miolo
40
+ MIOLO_DB_DATABASE=miolo-sample
39
41
  MIOLO_DB_USER=postgres
40
42
  MIOLO_DB_PASSWORD=postgres
41
43
 
42
-
43
44
  #
44
45
  # Logging
45
46
  #
47
+
46
48
  MIOLO_LOG_LEVEL=info
47
49
  MIOLO_LOG_CONSOLE_ENABLED=true
48
50
  MIOLO_LOG_FILE_ENABLED=false
49
51
  MIOLO_LOG_MAIL_ENABLED=false
50
52
  #MIOLO_LOG_MAIL_LEVEL=warn
51
- MIOLO_LOG_MAIL_FROM=miolo-sample@afialapis.com
52
- MIOLO_LOG_MAIL_TO=devel@afialapis.com
53
+ MIOLO_LOG_MAIL_FROM=miolo-sample@miolo-sample.com
54
+ MIOLO_LOG_MAIL_TO=miolo-sample@miolo-sample.com
53
55
 
54
56
  #
55
57
  # Mailer
56
58
  #
59
+
57
60
  MIOLO_MAILER_SILENT=true
58
- MIOLO_MAILER_HOST=mail.afialapis.com
61
+ MIOLO_MAILER_HOST=mail.miolo-sample.com
59
62
  MIOLO_MAILER_PORT=25
60
- MIOLO_MAILER_FROM=miolo-sample@afialapis.com
61
- MIOLO_MAILER_TO=devel@afialapis.com
63
+ MIOLO_MAILER_FROM=miolo-sample@miolo-sample.com
64
+ MIOLO_MAILER_TO=miolo-sample@miolo-sample.com
62
65
 
63
66
  # MIOLO_MAILER_AUTH_METHOD=PLAIN # PLAIN / LOGIN
64
67
  # # If LOGIN, you need to specify:
@@ -68,25 +71,28 @@ MIOLO_MAILER_TO=devel@afialapis.com
68
71
  #
69
72
  # Cache
70
73
  #
74
+
71
75
  MIOLO_REDIS_HOSTNAME=127.0.0.1
72
76
  MIOLO_REDIS_HOSTNAME_DOCKER=redis
73
77
  MIOLO_REDIS_PORT=6379
74
78
 
75
79
  MIOLO_CACHE_TYPE=redis
76
- MIOLO_CACHE_VERSION=4
77
- MIOLO_CACHE_CALUSTRA_VERSION=4
80
+ MIOLO_CACHE_VERSION=1
81
+ MIOLO_CACHE_CALUSTRA_VERSION=1
78
82
  MIOLO_CACHE_CALUSTRA_TTL=86400000
79
- MIOLO_CACHE_SESSION_VERSION=4
83
+ MIOLO_CACHE_SESSION_VERSION=1
80
84
  MIOLO_CACHE_SESSION_TTL=864000000
81
85
 
82
86
  #
83
87
  # Others
84
88
  #
89
+
85
90
  MIOLO_DOTENVX_DEBUG=false
86
91
 
87
92
  #
88
93
  # Build
89
94
  #
95
+
90
96
  MIOLO_BUILD_HTML_FILE=./src/cli/index.html
91
97
  MIOLO_BUILD_CLIENT_ENTRY=./src/cli/entry-cli.jsx
92
98
  MIOLO_BUILD_CLIENT_DEST=./build/cli
@@ -1,11 +1,14 @@
1
+ #
1
2
  # General
2
3
  #
4
+
3
5
  MIOLO_NAME=miolo-sample
4
6
  MIOLO_INTRE_LOCALE=es
5
7
 
6
8
  #
7
9
  # HTTP
8
10
  #
11
+
9
12
  MIOLO_PORT=8001
10
13
  MIOLO_HOSTNAME=localhost
11
14
  MIOLO_HOSTNAME_DOCKER=0.0.0.0
@@ -21,37 +24,44 @@ MIOLO_GEOIP_LOCAL_IPS=127.0.0.1,172.22.0.1,172.19.0.1
21
24
  #
22
25
  # Session
23
26
  #
27
+
24
28
  MIOLO_SESSION_SALT=00000000-0000-0000-0000-000000000000
25
29
  MIOLO_SESSION_SECRET=00000000-0000-0000-0000-000000000000
26
30
  MIOLO_SESSION_MAX_AGE=864000000
27
31
  MIOLO_SESSION_SECURE=false
28
32
  MIOLO_SESSION_RENEW=true
29
33
  MIOLO_SESSION_SAME_SITE=lax # lax | strict
34
+
30
35
  #
31
36
  # Database
32
37
  #
33
- MIOLO_DB_DATABASE=miolo
38
+
39
+ MIOLO_DB_DIALECT=postgres
40
+ MIOLO_DB_DATABASE=miolo-sample
34
41
  MIOLO_DB_USER=postgres
35
42
  MIOLO_DB_PASSWORD=postgres
36
43
 
37
44
  #
38
45
  # Logging
39
46
  #
47
+
40
48
  MIOLO_LOG_LEVEL=info
41
49
  MIOLO_LOG_CONSOLE_ENABLED=false
42
50
  MIOLO_LOG_FILE_ENABLED=true
43
51
  MIOLO_LOG_MAIL_ENABLED=true
44
52
  MIOLO_LOG_MAIL_LEVEL=error
45
- MIOLO_LOG_MAIL_FROM=miolo@afialapis.com
46
- MIOLO_LOG_MAIL_TO=devel@afialapis.com
53
+ MIOLO_LOG_MAIL_FROM=miolo-sample@miolo-sample.com
54
+ MIOLO_LOG_MAIL_TO=miolo-sample@miolo-sample.com
47
55
 
48
56
  #
49
57
  # Mailer
50
58
  #
59
+
51
60
  MIOLO_MAILER_SILENT=false
52
- MIOLO_MAILER_HOST=mail.afialapis.com
53
- MIOLO_MAILER_FROM=miolo@afialapis.com
54
- MIOLO_MAILER_TO=devel@afialapis.com
61
+ MIOLO_MAILER_HOST=mail.miolo-sample.com
62
+ MIOLO_MAILER_PORT=25
63
+ MIOLO_MAILER_FROM=miolo-sample@miolo-sample.com
64
+ MIOLO_MAILER_TO=miolo-sample@miolo-sample.com
55
65
 
56
66
  MIOLO_MAILER_PORT=465
57
67
  MIOLO_MAILER_AUTH_METHOD=LOGIN
@@ -61,6 +71,7 @@ MIOLO_MAILER_SMTP_PASS=<pass>
61
71
  #
62
72
  # Cache
63
73
  #
74
+
64
75
  MIOLO_REDIS_HOSTNAME=127.0.0.1
65
76
  MIOLO_REDIS_HOSTNAME_DOCKER=redis
66
77
  MIOLO_REDIS_PORT=6379
@@ -75,11 +86,13 @@ MIOLO_CACHE_SESSION_TTL=864000000
75
86
  #
76
87
  # Others
77
88
  #
89
+
78
90
  MIOLO_DOTENVX_DEBUG=false
79
91
 
80
92
  #
81
93
  # Build
82
94
  #
95
+
83
96
  MIOLO_BUILD_HTML_FILE=./src/cli/index.html
84
97
  MIOLO_BUILD_CLIENT_ENTRY=./src/cli/entry-cli.jsx
85
98
  MIOLO_BUILD_CLIENT_DEST=./build/cli
@@ -0,0 +1,116 @@
1
+ #!/bin/bash
2
+
3
+ # Database initialization script for miolo-sample
4
+ # Usage: ./db/init.sh <database_name>
5
+
6
+ set -e # Exit on error
7
+
8
+ # Colors for output
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ NC='\033[0m' # No Color
13
+
14
+ DB_NAME=$1
15
+
16
+ if [ -z "$DB_NAME" ]; then
17
+ echo -e "${RED}Error: Database name is required${NC}"
18
+ echo "Usage: $0 <database_name>"
19
+ exit 1
20
+ fi
21
+
22
+ echo -e "${GREEN}[miolo-sample] Database initialization${NC}"
23
+ echo "Database: $DB_NAME"
24
+
25
+ # Get the directory where this script is located
26
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
27
+ SQL_DIR="$SCRIPT_DIR/sql"
28
+
29
+ # Check if PostgreSQL is installed
30
+ if ! command -v psql &> /dev/null; then
31
+ echo -e "${RED}Error: PostgreSQL client (psql) not found${NC}"
32
+ echo "Please install PostgreSQL first"
33
+ exit 1
34
+ fi
35
+
36
+ # Function to create database
37
+ create_database() {
38
+ local user=$1
39
+
40
+ if [ "$user" = "postgres" ]; then
41
+ echo -e "${YELLOW}Attempting to create database as postgres user...${NC}"
42
+ sudo -u postgres createdb "$DB_NAME" 2>/dev/null
43
+ else
44
+ echo -e "${YELLOW}Attempting to create database as current user...${NC}"
45
+ createdb "$DB_NAME" 2>/dev/null
46
+ fi
47
+ }
48
+
49
+ # Try to create database
50
+ DB_EXISTS=$(psql -lqt 2>/dev/null | cut -d \| -f 1 | grep -w "$DB_NAME" | wc -l)
51
+
52
+ if [ "$DB_EXISTS" -eq 1 ]; then
53
+ echo -e "${YELLOW}Database '$DB_NAME' already exists${NC}"
54
+ read -p "Drop and recreate? (y/N): " -n 1 -r
55
+ echo
56
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
57
+ echo "Dropping database..."
58
+ if dropdb "$DB_NAME" 2>/dev/null; then
59
+ echo -e "${GREEN}✓ Database dropped${NC}"
60
+ else
61
+ sudo -u postgres dropdb "$DB_NAME"
62
+ echo -e "${GREEN}✓ Database dropped (as postgres user)${NC}"
63
+ fi
64
+ else
65
+ echo "Skipping database creation"
66
+ exit 0
67
+ fi
68
+ fi
69
+
70
+ # Try to create database with current user first
71
+ if create_database "current"; then
72
+ echo -e "${GREEN}✓ Database '$DB_NAME' created${NC}"
73
+ elif create_database "postgres"; then
74
+ echo -e "${GREEN}✓ Database '$DB_NAME' created (as postgres user)${NC}"
75
+ else
76
+ echo -e "${RED}Error: Failed to create database${NC}"
77
+ echo ""
78
+ echo "To avoid using sudo, grant CREATEDB permission to your user:"
79
+ echo " sudo -u postgres psql -c \"ALTER USER $USER CREATEDB;\""
80
+ exit 1
81
+ fi
82
+
83
+ # Execute SQL files in order
84
+ echo ""
85
+ echo -e "${YELLOW}Executing SQL files...${NC}"
86
+
87
+ if [ ! -d "$SQL_DIR" ]; then
88
+ echo -e "${RED}Error: SQL directory not found: $SQL_DIR${NC}"
89
+ exit 1
90
+ fi
91
+
92
+ # Find all .sql files and sort them
93
+ SQL_FILES=$(find "$SQL_DIR" -name "*.sql" -type f | sort)
94
+
95
+ if [ -z "$SQL_FILES" ]; then
96
+ echo -e "${YELLOW}No SQL files found in $SQL_DIR${NC}"
97
+ else
98
+ for sql_file in $SQL_FILES; do
99
+ filename=$(basename "$sql_file")
100
+ echo -ne " Executing $filename... "
101
+
102
+ if psql -d "$DB_NAME" -f "$sql_file" -q 2>&1 | grep -q "ERROR"; then
103
+ echo -e "${RED}✗ Failed${NC}"
104
+ exit 1
105
+ else
106
+ echo -e "${GREEN}✓${NC}"
107
+ fi
108
+ done
109
+ fi
110
+
111
+ echo ""
112
+ echo -e "${GREEN}✓ Database initialization complete!${NC}"
113
+ echo ""
114
+ echo "Connection info:"
115
+ echo " Database: $DB_NAME"
116
+ echo " Connect: psql -d $DB_NAME"
@@ -0,0 +1,2 @@
1
+ DROP TABLE todo;
2
+ DROP TABLE u_user;
@@ -0,0 +1,30 @@
1
+ CREATE TABLE u_user (
2
+ --sqlite
3
+ --id INTEGER PRIMARY KEY AUTOINCREMENT,
4
+ id serial,
5
+ username text,
6
+ password text,
7
+ name text,
8
+ email text,
9
+ active integer,
10
+
11
+ admin boolean,
12
+
13
+ last_login_date integer,
14
+ last_login_ip text,
15
+ login_count integer DEFAULT 0,
16
+
17
+ last_conn_at integer,
18
+ created_at integer,
19
+ last_update_at integer
20
+ );
21
+
22
+
23
+ INSERT INTO u_user
24
+ (username, password, name, email)
25
+ VALUES
26
+ ('miolo-sample@miolo-sample.com',
27
+ '3dc91ce0dd374a6daf9ccaa4f64c5e0972eb2e7c9857a6aa524174897c0f7c55a3853e696ef8b4c3156f5fd39d65a49496a929f278ae96577e948fb85546e222',
28
+ 'miolo-sample',
29
+ 'miolo-sample@miolo-sample.com')
30
+ ;
@@ -0,0 +1,20 @@
1
+ create table todo (
2
+ --sqlite
3
+ --id INTEGER PRIMARY KEY AUTOINCREMENT,
4
+ id serial,
5
+ description text,
6
+ done boolean,
7
+ --sqlite
8
+ --created_at INTEGER DEFAULT (strftime('%s', 'now')),
9
+ --last_update_at INTEGER DEFAULT (strftime('%s', 'now')),
10
+ created_At int default extract(epoch from now()),
11
+ last_update_At int default extract(epoch from now()),
12
+ created_by int,
13
+ last_update_by int
14
+ );
15
+
16
+ INSERT INTO todo (description, done) VALUES ('Buy milk', false);
17
+ INSERT INTO todo (description, done) VALUES ('Buy eggs', true);
18
+ INSERT INTO todo (description, done) VALUES ('Buy bread', false);
19
+ INSERT INTO todo (description, done) VALUES ('Buy butter', true);
20
+ INSERT INTO todo (description, done) VALUES ('Buy cheese', false);
@@ -45,8 +45,8 @@
45
45
  "intre": "^3.0.0-beta.3",
46
46
  "joi": "^18.0.2",
47
47
  "lucide-react": "^0.563.0",
48
- "miolo-cli": "^3.0.0-beta.150",
49
- "miolo-react": "^3.0.0-beta.150",
48
+ "miolo-cli": "^3.0.0-beta.152",
49
+ "miolo-react": "^3.0.0-beta.152",
50
50
  "next-themes": "^0.4.6",
51
51
  "radix-ui": "^1.4.3",
52
52
  "react": "^19.2.4",
@@ -60,7 +60,7 @@
60
60
  "tw-animate-css": "^1.4.0"
61
61
  },
62
62
  "devDependencies": {
63
- "miolo": "^3.0.0-beta.150",
63
+ "miolo": "^3.0.0-beta.152",
64
64
  "sass-embedded": "^1.97.3",
65
65
  "xeira": "^2.0.0-beta.10"
66
66
  },
@@ -0,0 +1,29 @@
1
+ import { sha512 } from './crypt.mjs'
2
+
3
+ import fs from 'node:fs'
4
+ import path from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ function _loadSalt() {
8
+ let dir = path.dirname(fileURLToPath(import.meta.url))
9
+ while (dir !== path.parse(dir).root && !fs.existsSync(path.join(dir, 'package.json'))) {
10
+ dir = path.dirname(dir)
11
+ }
12
+ const env = fs.readFileSync(path.join(dir, '.env'), 'utf8')
13
+ return env.match(/^MIOLO_SESSION_SALT=(.*)$/m)?.[1]?.trim()
14
+ }
15
+
16
+
17
+
18
+
19
+ async function _pwd_for() {
20
+ const args = process.argv.slice(2)
21
+ const pwd = args[0]
22
+
23
+ const salt = _loadSalt()
24
+
25
+ const cpwd = sha512(pwd, salt)
26
+ console.log([salt, cpwd])
27
+ }
28
+
29
+ _pwd_for()