@mostajs/orm-cli 0.5.1 → 0.5.3
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/mostajs.sh +168 -0
- package/package.json +1 -1
package/bin/mostajs.sh
CHANGED
|
@@ -1798,6 +1798,8 @@ menu_replicator() {
|
|
|
1798
1798
|
echo -e " ${CYAN}7${RESET}) List CDC rules"
|
|
1799
1799
|
echo -e " ${CYAN}8${RESET}) Run a CDC sync + show stats"
|
|
1800
1800
|
echo -e " ${CYAN}9${RESET}) Remove a CDC rule"
|
|
1801
|
+
echo -e " ${CYAN}m${RESET}) ${BOLD}Open monitor${RESET} (live dashboard — localhost:14499)"
|
|
1802
|
+
echo -e " ${CYAN}s${RESET}) ${BOLD}Scaffold services${RESET} — services/replicator.mjs + services/monitor.mjs + package.json scripts"
|
|
1801
1803
|
echo -e " ${CYAN}v${RESET}) View the raw tree file"
|
|
1802
1804
|
echo -e " ${CYAN}c${RESET}) Clear (delete the tree file — DESTRUCTIVE)"
|
|
1803
1805
|
echo
|
|
@@ -1815,6 +1817,8 @@ menu_replicator() {
|
|
|
1815
1817
|
7) action_rep_list_rules ;;
|
|
1816
1818
|
8) action_rep_sync ;;
|
|
1817
1819
|
9) action_rep_remove_rule ;;
|
|
1820
|
+
m|M) action_rep_open_monitor ;;
|
|
1821
|
+
s|S) action_rep_scaffold_services ;;
|
|
1818
1822
|
v|V) action_rep_view_tree ;;
|
|
1819
1823
|
c|C) action_rep_clear ;;
|
|
1820
1824
|
b|B) return ;;
|
|
@@ -1823,6 +1827,111 @@ menu_replicator() {
|
|
|
1823
1827
|
menu_replicator
|
|
1824
1828
|
}
|
|
1825
1829
|
|
|
1830
|
+
# ------------------------------------------------------------
|
|
1831
|
+
# Scaffold background services (replicator + monitor) + package.json patch
|
|
1832
|
+
# ------------------------------------------------------------
|
|
1833
|
+
action_rep_scaffold_services() {
|
|
1834
|
+
header
|
|
1835
|
+
echo -e "${BOLD}${MAGENTA}▶ Scaffold background services${RESET}"
|
|
1836
|
+
echo
|
|
1837
|
+
echo -e " This will :"
|
|
1838
|
+
echo -e " 1. ${CYAN}services/replicator.mjs${RESET} (from @mostajs/replicator)"
|
|
1839
|
+
echo -e " 2. ${CYAN}services/monitor.mjs${RESET} (from @mostajs/replica-monitor)"
|
|
1840
|
+
echo -e " 3. patch ${CYAN}package.json${RESET} : scripts.replicator / monitor / dev:all"
|
|
1841
|
+
echo -e " 4. install ${CYAN}concurrently${RESET} if missing"
|
|
1842
|
+
echo
|
|
1843
|
+
if ! confirm "Proceed?"; then return; fi
|
|
1844
|
+
|
|
1845
|
+
# Ensure the scaffolders' packages are installed locally
|
|
1846
|
+
ensure_pkg "@mostajs/replicator" "@mostajs/replica-monitor" || { pause; return; }
|
|
1847
|
+
|
|
1848
|
+
local force_arg=""
|
|
1849
|
+
if confirm "Overwrite existing services/*.mjs if present?"; then force_arg="--force"; fi
|
|
1850
|
+
|
|
1851
|
+
# Call each scaffolder (uses the lib's own emit logic — single source of truth)
|
|
1852
|
+
echo
|
|
1853
|
+
echo -e "${CYAN}▶ scaffoldReplicatorService${RESET}"
|
|
1854
|
+
node --input-type=module -e "
|
|
1855
|
+
const { scaffoldReplicatorService } = await import('${PROJECT_ROOT}/node_modules/@mostajs/replicator/dist/scaffold.js');
|
|
1856
|
+
const r = scaffoldReplicatorService({ projectDir: '${PROJECT_ROOT}', force: ${force_arg:+true}${force_arg:-false} });
|
|
1857
|
+
console.log(' ' + (r.wrote ? '✓' : '•') + ' ' + r.action + ' : ' + r.path);
|
|
1858
|
+
" 2>&1 | sed 's/^/ /'
|
|
1859
|
+
|
|
1860
|
+
echo
|
|
1861
|
+
echo -e "${CYAN}▶ scaffoldMonitorService${RESET}"
|
|
1862
|
+
node --input-type=module -e "
|
|
1863
|
+
const { scaffoldMonitorService } = await import('${PROJECT_ROOT}/node_modules/@mostajs/replica-monitor/dist/scaffold.js');
|
|
1864
|
+
const r = scaffoldMonitorService({ projectDir: '${PROJECT_ROOT}', force: ${force_arg:+true}${force_arg:-false} });
|
|
1865
|
+
console.log(' ' + (r.wrote ? '✓' : '•') + ' ' + r.action + ' : ' + r.path);
|
|
1866
|
+
" 2>&1 | sed 's/^/ /'
|
|
1867
|
+
|
|
1868
|
+
# Patch package.json scripts
|
|
1869
|
+
echo
|
|
1870
|
+
echo -e "${CYAN}▶ patching package.json scripts${RESET}"
|
|
1871
|
+
if [[ ! -f "$PROJECT_ROOT/package.json" ]]; then
|
|
1872
|
+
warn " no package.json found — skipping scripts patch"
|
|
1873
|
+
else
|
|
1874
|
+
PROJECT="$PROJECT_ROOT" node --input-type=module -e "
|
|
1875
|
+
const fs = await import('node:fs');
|
|
1876
|
+
const path = process.env.PROJECT + '/package.json';
|
|
1877
|
+
const pkg = JSON.parse(fs.readFileSync(path, 'utf8'));
|
|
1878
|
+
pkg.scripts = pkg.scripts || {};
|
|
1879
|
+
const add = (key, val) => {
|
|
1880
|
+
if (pkg.scripts[key]) {
|
|
1881
|
+
console.log(' • ' + key + ' already set (kept as-is)');
|
|
1882
|
+
} else {
|
|
1883
|
+
pkg.scripts[key] = val;
|
|
1884
|
+
console.log(' ✓ added ' + key);
|
|
1885
|
+
}
|
|
1886
|
+
};
|
|
1887
|
+
add('replicator', 'node services/replicator.mjs');
|
|
1888
|
+
add('monitor', 'node services/monitor.mjs');
|
|
1889
|
+
add('dev:all', 'concurrently --kill-others-on-fail --names next,rep,mon -c blue,magenta,cyan \"npm:dev\" \"npm:replicator\" \"npm:monitor\"');
|
|
1890
|
+
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n');
|
|
1891
|
+
" 2>&1 | sed 's/^/ /'
|
|
1892
|
+
fi
|
|
1893
|
+
|
|
1894
|
+
# Ensure concurrently is installed (devDependency)
|
|
1895
|
+
echo
|
|
1896
|
+
echo -e "${CYAN}▶ checking concurrently${RESET}"
|
|
1897
|
+
if [[ -d "$PROJECT_ROOT/node_modules/concurrently" ]]; then
|
|
1898
|
+
ok " concurrently already installed"
|
|
1899
|
+
else
|
|
1900
|
+
if confirm "Install concurrently as a devDependency?"; then
|
|
1901
|
+
cd "$PROJECT_ROOT" || return 1
|
|
1902
|
+
local log_file="/tmp/mostajs-concurrently-$$.log"
|
|
1903
|
+
case "$PKG_MANAGER" in
|
|
1904
|
+
pnpm) pnpm add -D concurrently > "$log_file" 2>&1 & ;;
|
|
1905
|
+
yarn) yarn add -D concurrently > "$log_file" 2>&1 & ;;
|
|
1906
|
+
bun) bun add -d concurrently > "$log_file" 2>&1 & ;;
|
|
1907
|
+
*) npm install --save-dev concurrently --legacy-peer-deps > "$log_file" 2>&1 & ;;
|
|
1908
|
+
esac
|
|
1909
|
+
local pid=$! frames='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏' tick=0
|
|
1910
|
+
while kill -0 "$pid" 2>/dev/null; do
|
|
1911
|
+
local f="${frames:$((tick % 10)):1}"
|
|
1912
|
+
printf "\r ${YELLOW}%s${RESET} installing concurrently ${DIM}(%ds)${RESET} " "$f" "$((tick / 5))"
|
|
1913
|
+
tick=$((tick + 1)); sleep 0.2
|
|
1914
|
+
done
|
|
1915
|
+
wait "$pid"; local rc=$?
|
|
1916
|
+
printf "\r%60s\r" ""
|
|
1917
|
+
if [[ $rc -eq 0 ]]; then ok " concurrently installed"
|
|
1918
|
+
else err " install failed (see $log_file)"; tail -3 "$log_file"
|
|
1919
|
+
fi
|
|
1920
|
+
rm -f "$log_file"
|
|
1921
|
+
fi
|
|
1922
|
+
fi
|
|
1923
|
+
|
|
1924
|
+
echo
|
|
1925
|
+
echo -e "${BOLD}${GREEN}✓ Scaffold complete.${RESET}"
|
|
1926
|
+
echo
|
|
1927
|
+
echo -e " ${BOLD}Next steps :${RESET}"
|
|
1928
|
+
echo -e " 1. ${CYAN}mostajs${RESET} → menu r → add replicas + CDC rules (writes replicator-tree.json)"
|
|
1929
|
+
echo -e " 2. ${CYAN}npm run dev:all${RESET} — starts Next + replicator + monitor in parallel"
|
|
1930
|
+
echo -e " or individually : ${CYAN}npm run replicator${RESET} / ${CYAN}npm run monitor${RESET}"
|
|
1931
|
+
echo -e " 3. Open ${CYAN}http://localhost:14499${RESET} for the live dashboard"
|
|
1932
|
+
pause
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1826
1935
|
action_rep_add_replica() {
|
|
1827
1936
|
local project name role dialect uri lag
|
|
1828
1937
|
project=$(ask "Project name" "default")
|
|
@@ -1963,6 +2072,65 @@ action_rep_remove_rule() {
|
|
|
1963
2072
|
pause
|
|
1964
2073
|
}
|
|
1965
2074
|
|
|
2075
|
+
action_rep_open_monitor() {
|
|
2076
|
+
header
|
|
2077
|
+
echo -e "${BOLD}${MAGENTA}▶ Open replica-monitor dashboard${RESET}"
|
|
2078
|
+
echo
|
|
2079
|
+
# Ensure the monitor package is installed
|
|
2080
|
+
if [[ ! -d "$PROJECT_ROOT/node_modules/@mostajs/replica-monitor" ]]; then
|
|
2081
|
+
warn "@mostajs/replica-monitor not installed in this project."
|
|
2082
|
+
if confirm "Install it now?"; then
|
|
2083
|
+
ensure_pkg "@mostajs/replica-monitor" || { pause; return; }
|
|
2084
|
+
else
|
|
2085
|
+
pause; return
|
|
2086
|
+
fi
|
|
2087
|
+
fi
|
|
2088
|
+
local tree_file
|
|
2089
|
+
tree_file=$(_replicator_tree_file)
|
|
2090
|
+
local port
|
|
2091
|
+
port=$(ask "Port" "14499")
|
|
2092
|
+
local token
|
|
2093
|
+
token=$(ask "Auth token (empty = no auth, local-only)" "")
|
|
2094
|
+
local url_suffix=""
|
|
2095
|
+
[[ -n "$token" ]] && url_suffix="?token=${token}"
|
|
2096
|
+
|
|
2097
|
+
local log_file="$PROJECT_ROOT/.mostajs/monitor.log"
|
|
2098
|
+
local pid_file="$PROJECT_ROOT/.mostajs/monitor.pid"
|
|
2099
|
+
|
|
2100
|
+
# If already running (pid file exists + process alive) : just open the URL.
|
|
2101
|
+
if [[ -f "$pid_file" ]] && kill -0 "$(cat "$pid_file" 2>/dev/null)" 2>/dev/null; then
|
|
2102
|
+
ok "Monitor already running at http://127.0.0.1:${port}"
|
|
2103
|
+
else
|
|
2104
|
+
# Spawn in background
|
|
2105
|
+
echo -e " ${DIM}spawning mostajs-monitor …${RESET}"
|
|
2106
|
+
MONITOR_TREE="$tree_file" MONITOR_PORT="$port" MONITOR_TOKEN="$token" \
|
|
2107
|
+
nohup node "$PROJECT_ROOT/node_modules/@mostajs/replica-monitor/dist/cli.js" \
|
|
2108
|
+
--tree "$tree_file" --port "$port" --runtime "$PROJECT_ROOT" \
|
|
2109
|
+
${token:+--token "$token"} \
|
|
2110
|
+
> "$log_file" 2>&1 &
|
|
2111
|
+
local pid=$!
|
|
2112
|
+
echo "$pid" > "$pid_file"
|
|
2113
|
+
sleep 1
|
|
2114
|
+
if kill -0 "$pid" 2>/dev/null; then
|
|
2115
|
+
ok "Monitor started (pid=$pid) → http://127.0.0.1:${port}${url_suffix}"
|
|
2116
|
+
dim " logs : $log_file"
|
|
2117
|
+
dim " stop : kill \$(cat $pid_file) or menu r → m again then Ctrl+C"
|
|
2118
|
+
else
|
|
2119
|
+
err "Monitor failed to start — check $log_file"
|
|
2120
|
+
cat "$log_file" | tail -10
|
|
2121
|
+
pause; return
|
|
2122
|
+
fi
|
|
2123
|
+
fi
|
|
2124
|
+
|
|
2125
|
+
# Try to open in default browser
|
|
2126
|
+
if command -v xdg-open >/dev/null 2>&1; then
|
|
2127
|
+
xdg-open "http://127.0.0.1:${port}${url_suffix}" >/dev/null 2>&1 &
|
|
2128
|
+
elif command -v open >/dev/null 2>&1; then
|
|
2129
|
+
open "http://127.0.0.1:${port}${url_suffix}" >/dev/null 2>&1 &
|
|
2130
|
+
fi
|
|
2131
|
+
pause
|
|
2132
|
+
}
|
|
2133
|
+
|
|
1966
2134
|
action_rep_view_tree() {
|
|
1967
2135
|
local tree_file
|
|
1968
2136
|
tree_file=$(_replicator_tree_file)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/orm-cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Universal CLI to integrate @mostajs/orm into any project — one-shot `mostajs bootstrap` migrates a Prisma project (codemod + deps + schema convert + DDL) to 13 databases with zero code change.",
|
|
5
5
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|