miolo 2.0.0-beta.2 → 2.0.0-beta.21

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": "2.0.0-beta.2",
3
+ "version": "2.0.0-beta.21",
4
4
  "description": "all-in-one koa-based server",
5
5
  "author": "Donato Lorenzo <donato@afialapis.com>",
6
6
  "contributors": [
@@ -15,6 +15,9 @@
15
15
  },
16
16
  "homepage": "https://www.afialapis.com/os/miolo",
17
17
  "license": "MIT",
18
+ "bin": {
19
+ "miolo": "./bin/index.mjs"
20
+ },
18
21
  "exports": {
19
22
  "./server": {
20
23
  "default": "./dist/server/miolo.server.node.mjs"
@@ -23,15 +26,14 @@
23
26
  "default": "./src/server/server-dev.mjs"
24
27
  },
25
28
  "./cli": {
26
- "import": "./src/cli/index.mjs",
27
29
  "default": "./dist/cli/miolo.cli.umd.js"
28
30
  },
29
31
  "./cli-react": {
30
- "import": "./src/cli-react/index.mjs",
31
32
  "default": "./dist/cli-react/miolo.cli-react.umd.js"
32
33
  }
33
34
  },
34
35
  "files": [
36
+ "bin",
35
37
  "src",
36
38
  "logo",
37
39
  "dist"
@@ -47,37 +49,32 @@
47
49
  "server-clean": "rm -fr ./dist/server/*",
48
50
  "server-bundle": "npx xeira bundle --target=node --source_index=./src/server/index.mjs --bundle_folder=./dist/server --bundle_name=miolo.server --bundle_extension=node.mjs",
49
51
  "server-dist": "npm run server-clean && npm run server-bundle",
50
-
51
52
  "YY-server-dev-clean": "rm -fr ./dist/server-dev/*",
52
53
  "YY-server-dev-bundle": "npx xeira bundle --target=node --source_index=./src/server/server-dev.mjs --bundle_folder=./dist/server-dev --bundle_name=miolo.server.dev --bundle_extension=node.mjs",
53
54
  "YY-server-dev-dist": "npm run server-dev-clean && npm run server-dev-bundle",
54
-
55
55
  "dist": "npm run cli-dist && npm run cli-react-dist && npm run server-dist",
56
56
  "site": "npx xeira site",
57
57
  "test": "npx xeira test --files=./test/index.mjs",
58
-
59
58
  "X_pre-publish": "npm run test && npm run dist && npm run site",
60
- "pre-publish": "npm run dist && npm run site",
61
-
62
-
59
+ "pre-publish": "npm run dist && npm run site",
63
60
  "xxx_demo-guest": "rm -fr ./demo/build/miolo-demo-guest* && node demo/run.cjs --guest",
64
61
  "xxx_demo-basic": "rm -fr ./demo/build/miolo-demo-basic* && node demo/run.cjs --basic",
65
62
  "xxx_demo-credentials": "rm -fr ./demo/build/miolo-demo-credentials* && node demo/run.cjs --credentials",
66
63
  "xxx_demo-credentials-debug": "rm -fr ./demo/build/miolo-demo-credentials* && DEBUG=winston* node demo/run.cjs --credentials",
67
64
  "xxx_demo": "npm run demo-credentials",
68
-
69
65
  "xxx_server-dist-esbuild": "npx esbuild ./src/server/index.mjs --bundle --platform=node --outfile=dist/server/server.mjs --format=esm --external:@babel/preset-typescript --external:lightningcss --external:tty",
70
-
71
66
  "xxx_demo-vite": "AUTH_TYPE=credentials node demo/server/server.mjs",
72
67
  "xxx_demo-vite-prod": "NODE_ENV=production AUTH_TYPE=credentials node demo/server/server.mjs",
73
68
  "xxx_demo-vite-build-client": "vite build --outDir demo/dist/client",
74
69
  "xxx_demo-vite-build-server": "vite build --outDir demo/dist/server --ssr demo/server/ssr/entry-server.jsx"
75
70
  },
76
71
  "dependencies": {
72
+ "@babel/plugin-proposal-decorators": "^7.25.9",
77
73
  "@koa/bodyparser": "^5.1.1",
78
74
  "@koa/cors": "^5.0.0",
79
75
  "@koa/router": "^13.1.0",
80
76
  "@maxmind/geoip2-node": "^6.0.0",
77
+ "@vitejs/plugin-react": "^4.3.4",
81
78
  "cacheiro": "^0.4.0",
82
79
  "calustra": "^0.15.0",
83
80
  "cron": "^4.1.4",
@@ -102,24 +99,18 @@
102
99
  "socket.io": "^4.8.1",
103
100
  "socket.io-client": "^4.8.1",
104
101
  "tinguir": "^0.0.7",
102
+ "vite": "^6.2.5",
105
103
  "winston": "^3.17.0",
106
- "winston-daily-rotate-file": "^5.0.0"
104
+ "winston-daily-rotate-file": "^5.0.0",
105
+ "xeira": "^1.1.10",
106
+ "yargs-parser": "^21.1.1"
107
107
  },
108
108
  "peerDependencies": {
109
109
  "react": "^18.3.1",
110
110
  "react-dom": "^18.3.1"
111
111
  },
112
112
  "devDependencies": {
113
- "@babel/core": "^7.26.10",
114
- "@babel/preset-env": "7.26.9",
115
- "@babel/preset-react": "7.26.3",
116
- "@babel/register": "7.25.9",
117
- "@vitejs/plugin-react": "^4.3.4",
118
- "babel-plugin-transform-import-meta": "^2.3.2",
119
- "esbuild": "^0.25.2",
120
- "node-fetch": "^3.3.2",
121
- "vite": "^6.2.5",
122
- "xeira": "^1.1.9"
113
+ "node-fetch": "^3.3.2"
123
114
  },
124
115
  "eslintConfig": {
125
116
  "extends": [
@@ -14,7 +14,7 @@ export function json_to_query_string(obj) {
14
14
  }
15
15
  }
16
16
  }
17
- return uparams.toString()
17
+ return `?${uparams.toString()}`
18
18
  }
19
19
  return ''
20
20
  }
@@ -332,11 +332,11 @@ export default {
332
332
  // {
333
333
  // name,
334
334
  // cronTime,
335
- // onTick(miolo, onComplete),
335
+ // onTick: async (miolo, onComplete),
336
336
  // Notice that if task runs too fast, you may see that
337
337
  // onTick is actually never run, but onComplete is.
338
338
  // Consider passing a higher interval on cronTime
339
- // onComplete(miolo),
339
+ // onComplete: async (miolo),
340
340
  // timezone, context, runOnInit, utcOffset, unrefTimeout
341
341
  // }
342
342
  // check https://github.com/kelektiv/node-cron#readme
@@ -414,5 +414,12 @@ export default {
414
414
  // html: '',
415
415
  // loader: async (ctx) => {}
416
416
  },
417
+
418
+ dev: {
419
+ watcher: {
420
+ enabled: true,
421
+ // dirs: [] By default, server's entry dir
422
+ },
423
+ }
417
424
  };
418
425
 
@@ -2,8 +2,8 @@ export function sys_email_queue_config() {
2
2
  return {
3
3
  name: 'Emailer',
4
4
  cronTime: '* * * * *',
5
- onTick: (miolo, _onCompleted) => {
6
- miolo.emailer.queue_send_emails(miolo.logger)
5
+ onTick: async (miolo, _onCompleted) => {
6
+ await miolo.emailer.queue_send_emails(miolo.logger)
7
7
  },
8
8
  start: true
9
9
  }
@@ -52,9 +52,9 @@ export function init_cron(app, custom) {
52
52
  return jobInfo
53
53
  }
54
54
 
55
- const _start_job = (jobInfo) => {
55
+ const _start_job = async (jobInfo) => {
56
56
  try {
57
- jobInfo.job.start()
57
+ await jobInfo.job.start()
58
58
  jobInfo.isActive= true
59
59
  logger.debug(`[cron][Job ${cyan(jobInfo.name)}] ${green_bold('started!')}`)
60
60
  return 1
@@ -65,26 +65,26 @@ export function init_cron(app, custom) {
65
65
  }
66
66
  }
67
67
 
68
- const _start_job_by_idx_or_name = (idxOrName) => {
68
+ const _start_job_by_idx_or_name = async (idxOrName) => {
69
69
  const jobInfo = _find_job_by_idx_or_name(idxOrName)
70
70
  if (jobInfo) {
71
- const done = _start_job(jobInfo)
71
+ const done = await _start_job(jobInfo)
72
72
  return [done, jobInfo.name]
73
73
  }
74
74
  return [0, '']
75
75
  }
76
76
 
77
- const _start_all_jobs = () => {
77
+ const _start_all_jobs = async () => {
78
78
  try {
79
79
  let started= [], errors= []
80
- jobInfos.map(jobInfo => {
81
- const done= _start_job(jobInfo)
80
+ for (const jobInfo of jobInfos) {
81
+ const done= await _start_job(jobInfo)
82
82
  if (done == 1) {
83
83
  started.push(jobInfo.name)
84
84
  } else {
85
85
  errors.push(jobInfo.name)
86
86
  }
87
- })
87
+ }
88
88
  if (started.length > 0) {
89
89
  logger.info(`[cron] Started ${started.length} jobs: ${started}`)
90
90
  }
@@ -97,9 +97,9 @@ export function init_cron(app, custom) {
97
97
 
98
98
  }
99
99
 
100
- const _stop_job = (jobInfo) => {
100
+ const _stop_job = async (jobInfo) => {
101
101
  try {
102
- jobInfo.job.stop()
102
+ await jobInfo.job.stop()
103
103
  jobInfo.isActive= false
104
104
  logger.debug(`[cron][Job ${cyan(jobInfo.name)}] ${yellow_bold('stopped!')}`)
105
105
  return 1
@@ -110,26 +110,26 @@ export function init_cron(app, custom) {
110
110
  }
111
111
  }
112
112
 
113
- const _stop_job_by_idx_or_name = (idxOrName) => {
113
+ const _stop_job_by_idx_or_name = async (idxOrName) => {
114
114
  const jobInfo = _find_job_by_idx_or_name(idxOrName)
115
115
  if (jobInfo) {
116
- const done = _stop_job(jobInfo)
116
+ const done = await _stop_job(jobInfo)
117
117
  return [done, jobInfo.name]
118
118
  }
119
119
  return [0, '']
120
120
  }
121
121
 
122
- const _stop_all_jobs = () => {
122
+ const _stop_all_jobs = async () => {
123
123
  try {
124
124
  let stopped= [], errors= []
125
- jobInfos.map(jobInfo => {
126
- const done= _stop_job(jobInfo)
125
+ for (const jobInfo of jobInfos) {
126
+ const done= await _stop_job(jobInfo)
127
127
  if (done == 1) {
128
128
  stopped.push(jobInfo.name)
129
129
  } else {
130
130
  errors.push(jobInfo.name)
131
131
  }
132
- })
132
+ }
133
133
  if (stopped.length > 0) {
134
134
  logger.info(`[cron] Stopped ${stopped.length} jobs: ${stopped}`)
135
135
  }
@@ -17,10 +17,10 @@ export function init_cron_job(miolo, config) {
17
17
  config?.cronTime || '*/5 * * * *',
18
18
 
19
19
  // onTick(miolo, onComplete)
20
- (onComplete) => {
20
+ async (onComplete) => {
21
21
  try {
22
22
  logger.silly(`[cron][Custom Job ${cyan(name)}] ${green_bold('ticks!')}`)
23
- config.onTick(miolo, onComplete)
23
+ await config.onTick(miolo, onComplete)
24
24
  } catch(e) {
25
25
  logger.error(`[cron][Custom Job ${cyan(name)}] Error at onTick()`)
26
26
  logger.error(e)
@@ -28,11 +28,11 @@ export function init_cron_job(miolo, config) {
28
28
  },
29
29
 
30
30
  // onComplete(miolo)
31
- () => {
31
+ async () => {
32
32
  logger.silly(`[cron][Custom Job ${cyan(name)}] ${green_bold('completed!')}`)
33
33
  if (config?.onComplete) {
34
34
  try {
35
- config.onComplete(miolo)
35
+ await config.onComplete(miolo)
36
36
  } catch(e) {
37
37
  logger.error(`[cron][Custom Job ${cyan(name)}] Error at onComplete()`)
38
38
  logger.error(e)
@@ -122,7 +122,7 @@ export function ipsum_config() {
122
122
  return {
123
123
  name: 'IPsum',
124
124
  cronTime: '0 0 * * *',
125
- onTick: (miolo, _onCompleted) => {
125
+ onTick: async (miolo, _onCompleted) => {
126
126
  const folder = miolo.config.http.ratelimit.ipsum_folder || _IPSUM_DEF_FOLDER
127
127
  ipsum_update(folder, (ips) => {
128
128
  miolo.logger.debug(`[cron][${cyan('IPsum')}] File downloaded. ${green(ips.length)} ips will be ${yellow('blacklisted')}!`)
@@ -48,7 +48,7 @@ export function sys_check_config() {
48
48
  return {
49
49
  name: 'SysCheck',
50
50
  cronTime: '0,15,30,45 * * * *',
51
- onTick: (miolo, _onCompleted) => {
51
+ onTick: async (miolo, _onCompleted) => {
52
52
  _sys_check_and_log(miolo.logger)
53
53
  },
54
54
  start: true
@@ -1,4 +1,5 @@
1
1
  import { miolo } from './server.mjs'
2
+ import { miolo_cron } from './server-cron.mjs'
2
3
  import { init_emailer_transporter as miolo_emailer} from './engines/emailer/index.mjs'
3
4
  import { init_logger as miolo_logger } from './engines/logger/index.mjs'
4
5
  import { init_parser as miolo_parser } from './engines/parser/index.mjs'
@@ -8,6 +9,7 @@ import { getConnection as miolo_db_connection} from 'calustra/conn-postgres'
8
9
 
9
10
  export {
10
11
  miolo,
12
+ miolo_cron,
11
13
  miolo_emailer,
12
14
  miolo_logger,
13
15
  miolo_parser,
@@ -13,7 +13,15 @@ export async function init_vite_dev_server_middleware(app, config) {
13
13
  vite = await createServer({
14
14
  server: { middlewareMode: true },
15
15
  appType: 'custom',
16
- plugins: [react.default()],
16
+ plugins: [react.default(
17
+ {
18
+ babel: {
19
+ plugins: [
20
+ ["@babel/plugin-proposal-decorators", { "legacy": true }]
21
+ ]
22
+ }
23
+ }
24
+ )],
17
25
  //
18
26
  base: config?.base || '/',
19
27
  root: config?.root || '',
@@ -0,0 +1,42 @@
1
+ import path from 'path'
2
+
3
+
4
+ // Resuse Vite Watcher
5
+ export async function init_watcher_dev_server_middleware(app, watcherConfig, ssrConfig) {
6
+ let watcher
7
+
8
+ const isEnabled = watcherConfig?.enabled === true
9
+ const isProduction = process.env.NODE_ENV === 'production'
10
+
11
+ if (isEnabled && (!isProduction)){
12
+
13
+ // Let's reuse Vite's cholkidar instance to listen to changes in server code
14
+ watcher = app.vite.watcher
15
+
16
+ // Extra dirs to watch
17
+ const serverDirsToWatch = watcherConfig?.dirs || ['server', 'src/server']
18
+
19
+ // Listen to changes in the extra dirs
20
+ serverDirsToWatch.forEach((dir) => {
21
+ watcher.add(path.resolve(process.cwd(), dir))
22
+ app.context.miolo.logger.info(`[watcher] Vite is now watching for changes also in: ${dir}`)
23
+ })
24
+
25
+ // Listen to changes in the extra dirs
26
+ watcher.on('change', async (filePath) => {
27
+ let isCustom = false
28
+ serverDirsToWatch.forEach((dir) => {
29
+ if (filePath.startsWith(path.resolve(process.cwd(), dir))) {
30
+ isCustom = true
31
+ }
32
+ })
33
+ if (!isCustom) return // Ignore changes outside the custom watched directories
34
+ app.context.miolo.logger.info(`[watcher] File changed: ${filePath}. Reloading server...`)
35
+
36
+ await app.stop()
37
+ process.send('miolo_restart') // Envía un mensaje al proceso padre para reiniciar
38
+ })
39
+ }
40
+
41
+ app.watcher= watcher
42
+ }
@@ -0,0 +1,40 @@
1
+ import { init_config } from './config/index.mjs'
2
+ import { init_context_middleware } from './middleware/context/index.mjs'
3
+ import { init_cron } from './engines/cron/index.mjs'
4
+
5
+ export async function miolo_cron(sconfig) {
6
+
7
+ const app = {
8
+ use: () => {},
9
+ context: {}
10
+ }
11
+
12
+ // Init some pieces
13
+ const config = init_config(sconfig)
14
+
15
+ // attach to app some custom miolo methods
16
+ init_context_middleware(app, config)
17
+
18
+
19
+ // Init cron (will not start jobs yet)
20
+ init_cron(app, config?.cron)
21
+
22
+ // Util callbacks
23
+ app.start = async () => {
24
+ // Init and reset db connection
25
+ await app.context.miolo.db.init_connection()
26
+ await app.cron.start()
27
+ }
28
+
29
+ app.stop = async () => {
30
+ await app.context.miolo.db.drop_connections()
31
+ await app.cron.stop()
32
+ }
33
+
34
+ app.restart = async () => {
35
+ await app.stop()
36
+ await app.start()
37
+ }
38
+
39
+ return app
40
+ }
@@ -1,5 +1,6 @@
1
1
  import { miolo } from "./server.mjs"
2
2
  import { init_vite_dev_server_middleware } from './middleware/vite/devserver.mjs'
3
+ import { init_watcher_dev_server_middleware } from './middleware/vite/watcher.mjs'
3
4
 
4
5
  /**
5
6
  * We use two separated servers
@@ -18,6 +19,7 @@ export async function miolo_dev(sconfig) {
18
19
  // Vite DEV server init
19
20
  const devInit= async (app, config) => {
20
21
  await init_vite_dev_server_middleware(app, config.vite)
22
+ await init_watcher_dev_server_middleware(app, config.dev.watcher, config.ssr)
21
23
  }
22
24
 
23
25
  // Vite SSR side
@@ -112,13 +112,16 @@ async function miolo(sconfig, devInit= undefined, devRender= undefined) {
112
112
  await app.context.miolo.db.init_connection()
113
113
 
114
114
  await app.http.start()
115
- app.cron.start()
115
+ await app.cron.start()
116
116
  }
117
117
 
118
118
  app.stop = async () => {
119
- app.context.miolo.db.drop_connections()
119
+ await app.context.miolo.db.drop_connections()
120
120
  await app.http.stop()
121
- app.cron.stop()
121
+ await app.cron.stop()
122
+ if (app?.vite) {
123
+ app.vite.close()
124
+ }
122
125
  }
123
126
 
124
127
  app.restart = async () => {