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
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import fs from "node:fs"
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
import { transformPackageJson } from "./pkgjson.mjs"
|
|
4
|
+
|
|
5
|
+
// Text file extensions to transform
|
|
6
|
+
const TEXT_EXTENSIONS = [
|
|
7
|
+
".js",
|
|
8
|
+
".jsx",
|
|
9
|
+
".mjs",
|
|
10
|
+
".ts",
|
|
11
|
+
".tsx",
|
|
12
|
+
".json",
|
|
13
|
+
".env",
|
|
14
|
+
".md",
|
|
15
|
+
".html",
|
|
16
|
+
".css",
|
|
17
|
+
".scss",
|
|
18
|
+
".sass",
|
|
19
|
+
".yml",
|
|
20
|
+
".yaml",
|
|
21
|
+
".toml",
|
|
22
|
+
".txt",
|
|
23
|
+
".gitignore",
|
|
24
|
+
".editorconfig",
|
|
25
|
+
".sh"
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
// Files and directories to exclude from copying
|
|
29
|
+
const EXCLUDE_PATTERNS = ["node_modules", "dist", "build", ".git"]
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Checks if a file is a text file based on extension
|
|
33
|
+
*/
|
|
34
|
+
export function isTextFile(filePath) {
|
|
35
|
+
const ext = path.extname(filePath).toLowerCase()
|
|
36
|
+
return (
|
|
37
|
+
TEXT_EXTENSIONS.includes(ext) ||
|
|
38
|
+
path.basename(filePath).startsWith(".") ||
|
|
39
|
+
path.basename(filePath) === "Dockerfile"
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Checks if a path should be excluded
|
|
45
|
+
*/
|
|
46
|
+
export function shouldExclude(itemPath) {
|
|
47
|
+
const basename = path.basename(itemPath)
|
|
48
|
+
return EXCLUDE_PATTERNS.some((pattern) => basename === pattern)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Replaces all occurrences of miolo-sample with the new app name
|
|
53
|
+
*/
|
|
54
|
+
export function transformContent(content, appName) {
|
|
55
|
+
return content.replace(/miolo-sample/g, appName)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Copies a directory recursively with transformations
|
|
60
|
+
*/
|
|
61
|
+
export function copyDirectory(src, dest, appName, options = {}) {
|
|
62
|
+
const { authType } = options
|
|
63
|
+
|
|
64
|
+
// Create destination if it doesn't exist
|
|
65
|
+
if (!fs.existsSync(dest)) {
|
|
66
|
+
fs.mkdirSync(dest, { recursive: true })
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const items = fs.readdirSync(src)
|
|
70
|
+
|
|
71
|
+
for (const item of items) {
|
|
72
|
+
const srcPath = path.join(src, item)
|
|
73
|
+
const destPath = path.join(dest, item)
|
|
74
|
+
const stat = fs.statSync(srcPath)
|
|
75
|
+
|
|
76
|
+
// Skip excluded items
|
|
77
|
+
if (shouldExclude(srcPath)) {
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (stat.isDirectory()) {
|
|
82
|
+
// Special handling for auth directory
|
|
83
|
+
if (srcPath.endsWith("src/server/miolo/auth")) {
|
|
84
|
+
// Create auth directory
|
|
85
|
+
fs.mkdirSync(destPath, { recursive: true })
|
|
86
|
+
|
|
87
|
+
// Copy only the selected auth file
|
|
88
|
+
const authFile = `${authType}.mjs`
|
|
89
|
+
const srcAuthFile = path.join(srcPath, authFile)
|
|
90
|
+
const destAuthFile = path.join(destPath, authFile)
|
|
91
|
+
|
|
92
|
+
if (fs.existsSync(srcAuthFile)) {
|
|
93
|
+
let content = fs.readFileSync(srcAuthFile, "utf8")
|
|
94
|
+
content = transformContent(content, appName)
|
|
95
|
+
fs.writeFileSync(destAuthFile, content, "utf8")
|
|
96
|
+
} else {
|
|
97
|
+
console.warn(`[miolo] Warning: Auth file ${authFile} not found, skipping`)
|
|
98
|
+
}
|
|
99
|
+
continue
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Recursively copy directories
|
|
103
|
+
copyDirectory(srcPath, destPath, appName, options)
|
|
104
|
+
} else {
|
|
105
|
+
// Copy and transform files
|
|
106
|
+
if (isTextFile(srcPath)) {
|
|
107
|
+
let content = fs.readFileSync(srcPath, "utf8")
|
|
108
|
+
|
|
109
|
+
// Special handling for package.json to also replace versions
|
|
110
|
+
if (srcPath.endsWith("package.json")) {
|
|
111
|
+
content = transformPackageJson(content, appName)
|
|
112
|
+
} else {
|
|
113
|
+
content = transformContent(content, appName)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
fs.writeFileSync(destPath, content, "utf8")
|
|
117
|
+
} else {
|
|
118
|
+
// Binary files - just copy
|
|
119
|
+
fs.copyFileSync(srcPath, destPath)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Copies only root-level files and specified directories
|
|
127
|
+
*/
|
|
128
|
+
export function copyTemplate(sourcePath, destPath, appName, options = {}) {
|
|
129
|
+
// Create destination directory
|
|
130
|
+
if (!fs.existsSync(destPath)) {
|
|
131
|
+
fs.mkdirSync(destPath, { recursive: true })
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Copy root-level files
|
|
135
|
+
const items = fs.readdirSync(sourcePath)
|
|
136
|
+
|
|
137
|
+
for (const item of items) {
|
|
138
|
+
const srcPath = path.join(sourcePath, item)
|
|
139
|
+
let destItemPath = path.join(destPath, item)
|
|
140
|
+
const stat = fs.statSync(srcPath)
|
|
141
|
+
|
|
142
|
+
if (shouldExclude(srcPath)) {
|
|
143
|
+
continue
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (stat.isFile()) {
|
|
147
|
+
// Special handling for gitignore -> .gitignore rename
|
|
148
|
+
// (npm doesn't include .gitignore in subdirectories, so we store it as gitignore)
|
|
149
|
+
if (item === "gitignore") {
|
|
150
|
+
destItemPath = path.join(destPath, ".gitignore")
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Copy root-level files
|
|
154
|
+
if (isTextFile(srcPath)) {
|
|
155
|
+
let content = fs.readFileSync(srcPath, "utf8")
|
|
156
|
+
|
|
157
|
+
// Special handling for package.json to also replace versions
|
|
158
|
+
if (srcPath.endsWith("package.json")) {
|
|
159
|
+
content = transformPackageJson(content, appName)
|
|
160
|
+
} else {
|
|
161
|
+
content = transformContent(content, appName)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
fs.writeFileSync(destItemPath, content, "utf8")
|
|
165
|
+
} else {
|
|
166
|
+
fs.copyFileSync(srcPath, destItemPath)
|
|
167
|
+
}
|
|
168
|
+
} else if (stat.isDirectory()) {
|
|
169
|
+
// Copy src/, db/, docker/, and .agent/ directories
|
|
170
|
+
if (item === "src" || item === "docker" || item === "db" || item === ".agent") {
|
|
171
|
+
copyDirectory(srcPath, destItemPath, appName, options)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from "node:fs"
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Updates docker-compose.yaml and Dockerfile with custom port
|
|
6
|
+
*/
|
|
7
|
+
export function updateDockerFiles(destPath, port) {
|
|
8
|
+
// Update docker-compose.yaml
|
|
9
|
+
const dockerComposePath = path.join(destPath, "docker/docker-compose.yaml")
|
|
10
|
+
if (fs.existsSync(dockerComposePath)) {
|
|
11
|
+
let content = fs.readFileSync(dockerComposePath, "utf8")
|
|
12
|
+
// Replace port mapping (e.g., "8001:8001" -> "9000:9000")
|
|
13
|
+
content = content.replace(/- "\d+:\d+"/g, `- "${port}:${port}"`)
|
|
14
|
+
fs.writeFileSync(dockerComposePath, content, "utf8")
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Update Dockerfile
|
|
18
|
+
const dockerfilePath = path.join(destPath, "docker/Dockerfile")
|
|
19
|
+
if (fs.existsSync(dockerfilePath)) {
|
|
20
|
+
let content = fs.readFileSync(dockerfilePath, "utf8")
|
|
21
|
+
// Replace EXPOSE port
|
|
22
|
+
content = content.replace(/EXPOSE \d+/, `EXPOSE ${port}`)
|
|
23
|
+
fs.writeFileSync(dockerfilePath, content, "utf8")
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { execSync } from "node:child_process"
|
|
2
|
+
import fs from "node:fs"
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import { fileURLToPath } from "node:url"
|
|
5
|
+
import { updateServerIndex } from "./auth.mjs"
|
|
6
|
+
import { copyTemplate } from "./copy.mjs"
|
|
7
|
+
import { updateDockerFiles } from "./docker.mjs"
|
|
8
|
+
import { updateEnvFile } from "./pkgjson.mjs"
|
|
9
|
+
// Import modular functions
|
|
10
|
+
import { validateAppName, validateAuthType } from "./validation.mjs"
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
13
|
+
const __dirname = path.dirname(__filename)
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Main create function
|
|
17
|
+
*/
|
|
18
|
+
export default async function create(appName, options = {}) {
|
|
19
|
+
try {
|
|
20
|
+
console.log("[miolo] Creating new miolo app:", appName)
|
|
21
|
+
|
|
22
|
+
// Validate app name
|
|
23
|
+
validateAppName(appName)
|
|
24
|
+
|
|
25
|
+
// Parse options
|
|
26
|
+
const { port, auth: authType = "passport", dest = `./${appName}` } = options
|
|
27
|
+
|
|
28
|
+
// Validate auth method
|
|
29
|
+
validateAuthType(authType)
|
|
30
|
+
|
|
31
|
+
// Get source path (template or miolo-sample for development)
|
|
32
|
+
// In development (monorepo), use miolo-sample directly
|
|
33
|
+
// In production (npm package), use bundled template folder
|
|
34
|
+
let sourcePath = path.resolve(__dirname, "../../../miolo-sample")
|
|
35
|
+
if (!fs.existsSync(sourcePath)) {
|
|
36
|
+
// Fallback to template folder (npm package)
|
|
37
|
+
sourcePath = path.resolve(__dirname, "../../template")
|
|
38
|
+
}
|
|
39
|
+
const destPath = path.resolve(process.cwd(), dest)
|
|
40
|
+
|
|
41
|
+
// Check if source exists
|
|
42
|
+
if (!fs.existsSync(sourcePath)) {
|
|
43
|
+
throw new Error(`Source template not found: ${sourcePath}`)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Check if destination already exists and has content
|
|
47
|
+
if (fs.existsSync(destPath)) {
|
|
48
|
+
// Allow if destination is current directory (.) or an empty directory
|
|
49
|
+
const isCwd = path.resolve(destPath) === process.cwd()
|
|
50
|
+
if (!isCwd) {
|
|
51
|
+
const items = fs.readdirSync(destPath)
|
|
52
|
+
// Filter out hidden files/dirs that are safe to ignore
|
|
53
|
+
const significantItems = items.filter(
|
|
54
|
+
(item) => !item.startsWith(".") && item !== "node_modules"
|
|
55
|
+
)
|
|
56
|
+
if (significantItems.length > 0) {
|
|
57
|
+
throw new Error(`Destination already exists and is not empty: ${destPath}`)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log("[miolo] Copying template from:", sourcePath)
|
|
63
|
+
console.log("[miolo] Creating app at:", destPath)
|
|
64
|
+
console.log("[miolo] Auth method:", authType)
|
|
65
|
+
if (port) {
|
|
66
|
+
console.log("[miolo] Port:", port)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Copy template files
|
|
70
|
+
copyTemplate(sourcePath, destPath, appName, { authType })
|
|
71
|
+
|
|
72
|
+
console.log("[miolo] Template copied successfully")
|
|
73
|
+
|
|
74
|
+
// Update .env with custom parameters
|
|
75
|
+
updateEnvFile(destPath, appName, { port })
|
|
76
|
+
|
|
77
|
+
// Update docker files with custom port
|
|
78
|
+
if (port) {
|
|
79
|
+
updateDockerFiles(destPath, port)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Update server/miolo/index.mjs with correct auth import
|
|
83
|
+
updateServerIndex(destPath, authType)
|
|
84
|
+
|
|
85
|
+
// Install dependencies
|
|
86
|
+
console.log("[miolo] Installing dependencies...")
|
|
87
|
+
try {
|
|
88
|
+
execSync("npm install", {
|
|
89
|
+
cwd: destPath,
|
|
90
|
+
stdio: "inherit"
|
|
91
|
+
})
|
|
92
|
+
console.log("[miolo] Dependencies installed successfully")
|
|
93
|
+
} catch (_error) {
|
|
94
|
+
console.warn("[miolo] Warning: Failed to install dependencies automatically")
|
|
95
|
+
console.warn('[miolo] Please run "npm install" manually in the project directory')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Initialize database
|
|
99
|
+
const dbInitScript = path.join(destPath, "db/init.sh")
|
|
100
|
+
if (fs.existsSync(dbInitScript)) {
|
|
101
|
+
console.log("")
|
|
102
|
+
console.log("[miolo] Database initialization")
|
|
103
|
+
console.log(
|
|
104
|
+
"[miolo] ⚠️ Note: This step may require sudo password if your user doesn't have CREATEDB permission"
|
|
105
|
+
)
|
|
106
|
+
console.log("[miolo] Database name will be:", appName)
|
|
107
|
+
|
|
108
|
+
// Make script executable
|
|
109
|
+
try {
|
|
110
|
+
fs.chmodSync(dbInitScript, 0o755)
|
|
111
|
+
} catch (_error) {
|
|
112
|
+
// Ignore chmod errors
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
execSync(`${dbInitScript} ${appName}`, {
|
|
117
|
+
cwd: destPath,
|
|
118
|
+
stdio: "inherit"
|
|
119
|
+
})
|
|
120
|
+
console.log("[miolo] ✅ Database initialized successfully")
|
|
121
|
+
} catch (_error) {
|
|
122
|
+
console.warn("[miolo] ⚠️ Warning: Database initialization failed or was skipped")
|
|
123
|
+
console.warn("[miolo] You can initialize it manually later by running:")
|
|
124
|
+
console.warn(`[miolo] cd ${dest} && ./db/init.sh ${appName}`)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log("")
|
|
129
|
+
console.log("[miolo] ✅ App created successfully!")
|
|
130
|
+
console.log("[miolo] To get started:")
|
|
131
|
+
console.log(` cd ${dest}`)
|
|
132
|
+
console.log(" npm run dev")
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error("[miolo] Error creating app:", error.message)
|
|
135
|
+
throw error
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import fs from "node:fs"
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
6
|
+
const __dirname = path.dirname(__filename)
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get miolo version from package.json
|
|
10
|
+
*/
|
|
11
|
+
export function getMioloVersion() {
|
|
12
|
+
try {
|
|
13
|
+
const mioloPackageJsonPath = path.resolve(__dirname, "../../package.json")
|
|
14
|
+
const mioloPackageJson = JSON.parse(fs.readFileSync(mioloPackageJsonPath, "utf8"))
|
|
15
|
+
return `^${mioloPackageJson.version}`
|
|
16
|
+
} catch (_error) {
|
|
17
|
+
console.warn("[miolo] Warning: Could not read miolo version, using latest")
|
|
18
|
+
return "^3.0.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Transforms package.json content by replacing app name and file:../ references
|
|
24
|
+
*/
|
|
25
|
+
export function transformPackageJson(content, appName) {
|
|
26
|
+
// First, replace app name
|
|
27
|
+
let transformed = content.replace(/miolo-sample/g, appName)
|
|
28
|
+
|
|
29
|
+
// Then, replace file:../ references with npm versions
|
|
30
|
+
const version = getMioloVersion()
|
|
31
|
+
transformed = transformed.replace(
|
|
32
|
+
/"file:\.\.\/(miolo-cli|miolo-react|miolo-model|miolo)"/g,
|
|
33
|
+
`"${version}"`
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return transformed
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Updates the .env and .env.production files with custom parameters
|
|
41
|
+
*/
|
|
42
|
+
export function updateEnvFile(destPath, _appName, options = {}) {
|
|
43
|
+
const { port } = options
|
|
44
|
+
|
|
45
|
+
// Update .env
|
|
46
|
+
const envPath = path.join(destPath, ".env")
|
|
47
|
+
if (fs.existsSync(envPath)) {
|
|
48
|
+
let content = fs.readFileSync(envPath, "utf8")
|
|
49
|
+
|
|
50
|
+
// Update port if specified
|
|
51
|
+
if (port) {
|
|
52
|
+
content = content.replace(/MIOLO_PORT=\d+/, `MIOLO_PORT=${port}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fs.writeFileSync(envPath, content, "utf8")
|
|
56
|
+
} else {
|
|
57
|
+
console.warn("[miolo] Warning: .env file not found")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Update .env.production
|
|
61
|
+
const envProdPath = path.join(destPath, ".env.production")
|
|
62
|
+
if (fs.existsSync(envProdPath)) {
|
|
63
|
+
let content = fs.readFileSync(envProdPath, "utf8")
|
|
64
|
+
|
|
65
|
+
// Update port if specified
|
|
66
|
+
if (port) {
|
|
67
|
+
content = content.replace(/MIOLO_PORT=\d+/, `MIOLO_PORT=${port}`)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fs.writeFileSync(envProdPath, content, "utf8")
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs"
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import { fileURLToPath } from "node:url"
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
7
|
+
const __dirname = path.dirname(__filename)
|
|
8
|
+
|
|
9
|
+
console.log("[prepare-template] Starting template preparation...")
|
|
10
|
+
|
|
11
|
+
// Paths
|
|
12
|
+
const mioloSamplePath = path.resolve(__dirname, "../../../miolo-sample")
|
|
13
|
+
const templatePath = path.resolve(__dirname, "../../template")
|
|
14
|
+
const mioloPackageJsonPath = path.resolve(__dirname, "../../package.json")
|
|
15
|
+
|
|
16
|
+
// Read miolo version
|
|
17
|
+
const mioloPackageJson = JSON.parse(fs.readFileSync(mioloPackageJsonPath, "utf8"))
|
|
18
|
+
const version = `^${mioloPackageJson.version}`
|
|
19
|
+
|
|
20
|
+
console.log(`[prepare-template] Using version: ${version}`)
|
|
21
|
+
|
|
22
|
+
// Step 1: Remove existing template directory
|
|
23
|
+
if (fs.existsSync(templatePath)) {
|
|
24
|
+
console.log("[prepare-template] Removing existing template directory...")
|
|
25
|
+
fs.rmSync(templatePath, { recursive: true, force: true })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Step 2: Create template directory
|
|
29
|
+
console.log("[prepare-template] Creating template directory...")
|
|
30
|
+
fs.mkdirSync(templatePath, { recursive: true })
|
|
31
|
+
|
|
32
|
+
// Step 3: Copy files from miolo-sample to template
|
|
33
|
+
console.log("[prepare-template] Copying files from miolo-sample...")
|
|
34
|
+
|
|
35
|
+
// Files to copy (note: .gitignore renamed to gitignore to avoid npm exclusion)
|
|
36
|
+
const filesToCopy = [
|
|
37
|
+
{ src: ".env", dest: ".env" },
|
|
38
|
+
{ src: ".env.production", dest: ".env.production" },
|
|
39
|
+
{ src: ".editorconfig", dest: ".editorconfig" },
|
|
40
|
+
{ src: ".gitignore", dest: "gitignore" }, // Rename to avoid npm ignoring it
|
|
41
|
+
{ src: "components.json", dest: "components.json" },
|
|
42
|
+
{ src: "jsconfig.json", dest: "jsconfig.json" },
|
|
43
|
+
{ src: "package.json", dest: "package.json" },
|
|
44
|
+
{ src: "biome.json", dest: "biome.json" },
|
|
45
|
+
{ src: "postcss.config.js", dest: "postcss.config.js" }
|
|
46
|
+
//{ src: 'vite.config.mjs', dest: 'vite.config.mjs' }
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
// Copy individual files
|
|
50
|
+
for (const { src, dest } of filesToCopy) {
|
|
51
|
+
const srcFile = path.join(mioloSamplePath, src)
|
|
52
|
+
const destFile = path.join(templatePath, dest)
|
|
53
|
+
|
|
54
|
+
if (fs.existsSync(srcFile)) {
|
|
55
|
+
fs.copyFileSync(srcFile, destFile)
|
|
56
|
+
console.log(`[prepare-template] ✓ Copied ${src}${src !== dest ? ` → ${dest}` : ""}`)
|
|
57
|
+
} else {
|
|
58
|
+
console.warn(`[prepare-template] ⚠ File not found: ${src}`)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Copy directories
|
|
63
|
+
const dirsToCopy = ["src", "docker", "db"]
|
|
64
|
+
|
|
65
|
+
for (const dir of dirsToCopy) {
|
|
66
|
+
const srcDir = path.join(mioloSamplePath, dir)
|
|
67
|
+
const destDir = path.join(templatePath, dir)
|
|
68
|
+
|
|
69
|
+
if (fs.existsSync(srcDir)) {
|
|
70
|
+
copyDirRecursive(srcDir, destDir)
|
|
71
|
+
console.log(`[prepare-template] ✓ Copied ${dir}/`)
|
|
72
|
+
} else {
|
|
73
|
+
console.warn(`[prepare-template] ⚠ Directory not found: ${dir}`)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Copy skills from workspace root
|
|
78
|
+
const skillsSrc = path.resolve(__dirname, "../../../../skills")
|
|
79
|
+
const skillsDest = path.join(templatePath, ".agent", "skills")
|
|
80
|
+
if (fs.existsSync(skillsSrc)) {
|
|
81
|
+
fs.mkdirSync(path.join(templatePath, ".agent"), { recursive: true })
|
|
82
|
+
copyDirRecursive(skillsSrc, skillsDest)
|
|
83
|
+
console.log("[prepare-template] ✓ Copied skills/")
|
|
84
|
+
} else {
|
|
85
|
+
console.warn("[prepare-template] ⚠ Skills directory not found at", skillsSrc)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Step 4: Update package.json versions
|
|
89
|
+
console.log("[prepare-template] Updating package.json versions...")
|
|
90
|
+
const templatePackageJsonPath = path.join(templatePath, "package.json")
|
|
91
|
+
const templatePackageJson = JSON.parse(fs.readFileSync(templatePackageJsonPath, "utf8"))
|
|
92
|
+
|
|
93
|
+
const replacements = {
|
|
94
|
+
"file:../miolo": version,
|
|
95
|
+
"file:../miolo-cli": version,
|
|
96
|
+
"file:../miolo-react": version
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let modified = false
|
|
100
|
+
|
|
101
|
+
// Update dependencies
|
|
102
|
+
if (templatePackageJson.dependencies) {
|
|
103
|
+
for (const [pkg, currentVersion] of Object.entries(templatePackageJson.dependencies)) {
|
|
104
|
+
if (replacements[currentVersion]) {
|
|
105
|
+
console.log(
|
|
106
|
+
`[prepare-template] ${pkg}: ${currentVersion} → ${replacements[currentVersion]}`
|
|
107
|
+
)
|
|
108
|
+
templatePackageJson.dependencies[pkg] = replacements[currentVersion]
|
|
109
|
+
modified = true
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Update devDependencies
|
|
115
|
+
if (templatePackageJson.devDependencies) {
|
|
116
|
+
for (const [pkg, currentVersion] of Object.entries(templatePackageJson.devDependencies)) {
|
|
117
|
+
if (replacements[currentVersion]) {
|
|
118
|
+
console.log(
|
|
119
|
+
`[prepare-template] ${pkg}: ${currentVersion} → ${replacements[currentVersion]}`
|
|
120
|
+
)
|
|
121
|
+
templatePackageJson.devDependencies[pkg] = replacements[currentVersion]
|
|
122
|
+
modified = true
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (modified) {
|
|
128
|
+
fs.writeFileSync(
|
|
129
|
+
templatePackageJsonPath,
|
|
130
|
+
JSON.stringify(templatePackageJson, null, 2) + "\n",
|
|
131
|
+
"utf8"
|
|
132
|
+
)
|
|
133
|
+
console.log("[prepare-template] ✅ Template package.json updated")
|
|
134
|
+
} else {
|
|
135
|
+
console.log("[prepare-template] No file:../ references found to replace")
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
console.log("[prepare-template] ✅ Template synchronized from miolo-sample")
|
|
139
|
+
|
|
140
|
+
// Helper function to copy directories recursively
|
|
141
|
+
function copyDirRecursive(src, dest) {
|
|
142
|
+
if (!fs.existsSync(dest)) {
|
|
143
|
+
fs.mkdirSync(dest, { recursive: true })
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const entries = fs.readdirSync(src, { withFileTypes: true })
|
|
147
|
+
|
|
148
|
+
for (const entry of entries) {
|
|
149
|
+
const srcPath = path.join(src, entry.name)
|
|
150
|
+
const destPath = path.join(dest, entry.name)
|
|
151
|
+
|
|
152
|
+
if (entry.isDirectory()) {
|
|
153
|
+
copyDirRecursive(srcPath, destPath)
|
|
154
|
+
} else {
|
|
155
|
+
fs.copyFileSync(srcPath, destPath)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation helper functions for create command
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Validates app name (alphanumeric + hyphens/underscores)
|
|
7
|
+
*/
|
|
8
|
+
export function validateAppName(name) {
|
|
9
|
+
if (!name) {
|
|
10
|
+
throw new Error("App name is required")
|
|
11
|
+
}
|
|
12
|
+
if (!/^[a-z0-9-_]+$/i.test(name)) {
|
|
13
|
+
throw new Error("App name must contain only alphanumeric characters, hyphens, and underscores")
|
|
14
|
+
}
|
|
15
|
+
return true
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Validates auth method
|
|
20
|
+
*/
|
|
21
|
+
export function validateAuthType(authType) {
|
|
22
|
+
const validAuthTypes = ["passport", "basic", "guest"]
|
|
23
|
+
if (!validAuthTypes.includes(authType)) {
|
|
24
|
+
throw new Error(`Invalid auth type: ${authType}. Valid options: ${validAuthTypes.join(", ")}`)
|
|
25
|
+
}
|
|
26
|
+
return true
|
|
27
|
+
}
|
package/bin/dev/dev.mjs
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import path from
|
|
3
|
-
import { fileURLToPath } from
|
|
4
|
-
import { fork } from 'node:child_process'
|
|
5
|
-
|
|
1
|
+
import { fork } from "node:child_process"
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
6
4
|
|
|
7
5
|
const __filename = fileURLToPath(import.meta.url)
|
|
8
6
|
const __dirname = path.dirname(__filename)
|
|
@@ -15,18 +13,32 @@ function _isProcessRunning(pid) {
|
|
|
15
13
|
try {
|
|
16
14
|
process.kill(pid, 0) // Sending a signal 0 does nothing but checks if the process exists
|
|
17
15
|
return true
|
|
18
|
-
} catch (
|
|
16
|
+
} catch (_) {
|
|
19
17
|
return false
|
|
20
18
|
}
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
async function startDevServerProcess({ appName }) {
|
|
24
|
-
const serverPath = path.join(__dirname,
|
|
25
|
-
|
|
21
|
+
async function startDevServerProcess({ appName, debug }) {
|
|
22
|
+
const serverPath = path.join(__dirname, "./dev_start.mjs")
|
|
23
|
+
|
|
24
|
+
const execArgv = []
|
|
25
|
+
if (debug === true) {
|
|
26
|
+
const newDebugPort = process.debugPort + 1
|
|
27
|
+
console.log(
|
|
28
|
+
`[${appName}][dev] Debugging enabled. Attaching debugger to child process on port ${newDebugPort}`
|
|
29
|
+
)
|
|
30
|
+
execArgv.push(`--inspect=${newDebugPort}`)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
serverProcess = fork(serverPath, [], {
|
|
34
|
+
execArgv: execArgv
|
|
35
|
+
})
|
|
26
36
|
|
|
27
|
-
console.log(
|
|
37
|
+
console.log(
|
|
38
|
+
`[${appName}][dev] Server process started with pid ${serverProcess.pid} from ${process.pid}`
|
|
39
|
+
)
|
|
28
40
|
|
|
29
|
-
serverProcess.on(
|
|
41
|
+
serverProcess.on("exit", (code, args) => {
|
|
30
42
|
console.log(`[${appName}][dev] Server process exited with code ${code} - ${args}`)
|
|
31
43
|
serverProcess = null
|
|
32
44
|
// Puedes implementar lógica de reintento aquí si es necesario
|
|
@@ -39,39 +51,36 @@ async function startDevServerProcess({ appName }) {
|
|
|
39
51
|
// } else if (code !== 0) {
|
|
40
52
|
// console.error(`[${serverName}][dev] Server failed to start after ${maxRetries} retries. Exiting.`)
|
|
41
53
|
// process.exit(1)
|
|
42
|
-
// }
|
|
54
|
+
// }
|
|
43
55
|
})
|
|
44
56
|
|
|
45
|
-
serverProcess.on(
|
|
46
|
-
if (message ===
|
|
57
|
+
serverProcess.on("message", (message) => {
|
|
58
|
+
if (message === "miolo_restart") {
|
|
47
59
|
console.log(`[${appName}][dev] Received restart signal. Restarting server...`)
|
|
48
60
|
|
|
49
61
|
const pidToKill = serverProcess ? serverProcess.pid : null
|
|
50
62
|
if (pidToKill) {
|
|
51
63
|
console.log(`[${appName}][dev] Killing process with PID: ${pidToKill}`)
|
|
52
64
|
// Clean kill
|
|
53
|
-
process.kill(pidToKill,
|
|
65
|
+
process.kill(pidToKill, "SIGTERM")
|
|
54
66
|
|
|
55
67
|
// Harder if still alive
|
|
56
68
|
setTimeout(() => {
|
|
57
69
|
if (_isProcessRunning(pidToKill)) {
|
|
58
|
-
process.kill(pidToKill,
|
|
70
|
+
process.kill(pidToKill, "SIGKILL")
|
|
59
71
|
}
|
|
60
72
|
}, 2000)
|
|
61
73
|
}
|
|
62
74
|
|
|
63
|
-
startDevServerProcess({ appName }) // Inicia un nuevo proceso
|
|
75
|
+
startDevServerProcess({ appName, debug }) // Inicia un nuevo proceso
|
|
64
76
|
}
|
|
65
77
|
})
|
|
66
78
|
}
|
|
67
79
|
|
|
68
|
-
|
|
69
|
-
export default async function(appName= undefined) {
|
|
70
|
-
|
|
71
|
-
|
|
80
|
+
export default async function (appName = undefined, debug = false) {
|
|
72
81
|
// Based on command line params or .env
|
|
73
82
|
appName = appName || process.env.MIOLO_NAME
|
|
74
|
-
|
|
83
|
+
|
|
75
84
|
console.log(`[${appName}][dev] Running DEV server`)
|
|
76
|
-
await startDevServerProcess({ appName })
|
|
85
|
+
await startDevServerProcess({ appName, debug })
|
|
77
86
|
}
|