@mostajs/orm-cli 0.1.0
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/LICENSE +29 -0
- package/README.md +138 -0
- package/bin/mostajs-launcher.cjs +35 -0
- package/bin/mostajs.bat +490 -0
- package/bin/mostajs.sh +994 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 19 November 2007
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 Dr Hamid MADANI <drmdh@msn.com>
|
|
5
|
+
|
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU Affero General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU Affero General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU Affero General Public License
|
|
17
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
COMMERCIAL LICENSE
|
|
20
|
+
|
|
21
|
+
For organizations that cannot comply with the AGPL open-source requirements,
|
|
22
|
+
a commercial license is available. Contact: drmdh@msn.com
|
|
23
|
+
|
|
24
|
+
The commercial license allows you to:
|
|
25
|
+
- Use the software in proprietary/closed-source projects
|
|
26
|
+
- Modify without publishing your source code
|
|
27
|
+
- Get priority support and SLA
|
|
28
|
+
|
|
29
|
+
Contact: Dr Hamid MADANI <drmdh@msn.com>
|
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# @mostajs/orm-cli
|
|
2
|
+
|
|
3
|
+
> **Universal interactive CLI for @mostajs/orm integration.**
|
|
4
|
+
> Auto-detects Prisma / OpenAPI / JSON Schema in any project, converts to EntitySchema[], tests with humans / mobiles / AI agents, and launches everything.
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/@mostajs/orm-cli)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
### Option 1 — npx (zero install)
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cd your/project
|
|
15
|
+
npx @mostajs/orm-cli
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Option 2 — global
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @mostajs/orm-cli
|
|
22
|
+
cd your/project
|
|
23
|
+
mostajs
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Option 3 — curl one-liner (Unix)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
curl -fsSL https://raw.githubusercontent.com/apolocine/mosta-orm-cli/main/install.sh | bash
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### Interactive menu (recommended)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cd your/project
|
|
38
|
+
mostajs
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The CLI auto-detects :
|
|
42
|
+
- **Prisma** : `prisma/schema.prisma`
|
|
43
|
+
- **OpenAPI** : `openapi.yaml`, `openapi.json`, `api.yaml`, `spec/openapi.yaml`, etc.
|
|
44
|
+
- **JSON Schema** : `schemas/*.json`
|
|
45
|
+
|
|
46
|
+
Menu :
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
1) Convert schema → EntitySchema[]
|
|
50
|
+
2) Configure database URIs (13 databases)
|
|
51
|
+
3) Initialize dialects (connect + create tables)
|
|
52
|
+
4) Tests menu (human / mobile / AI / curl / playwright)
|
|
53
|
+
5) Start services (Next.js + mosta-net)
|
|
54
|
+
6) Metrics & status
|
|
55
|
+
7) View logs
|
|
56
|
+
8) Health checks
|
|
57
|
+
9) Generate boilerplate (src/db.ts / .env.example)
|
|
58
|
+
0) About / Help
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Non-interactive subcommands
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
mostajs convert # auto-detect + convert
|
|
65
|
+
mostajs detect # print detected schemas
|
|
66
|
+
mostajs health # check tools + project state
|
|
67
|
+
mostajs version
|
|
68
|
+
mostajs help
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## What it does
|
|
72
|
+
|
|
73
|
+
### Tests menu — everything you need to verify
|
|
74
|
+
|
|
75
|
+
- **Human** : opens browser on `http://localhost:3000`
|
|
76
|
+
- **Mobile** : generates QR code for LAN URL (needs `qrencode`)
|
|
77
|
+
- **AI** : displays ready-to-paste Claude Desktop MCP config
|
|
78
|
+
- **curl** : smoke-tests all endpoints with status codes + times
|
|
79
|
+
- **Playwright** : runs existing test suite
|
|
80
|
+
|
|
81
|
+
### Config stored per-project
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
your-project/.mostajs/
|
|
85
|
+
├── config.env # URIs + ports
|
|
86
|
+
├── generated/entities.ts # EntitySchema[] (auto-generated)
|
|
87
|
+
└── logs/ # dev / convert / init logs
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Supported databases (13)
|
|
91
|
+
|
|
92
|
+
PostgreSQL · MySQL · MariaDB · SQLite · MS SQL Server · Oracle · DB2 · HANA · HSQLDB · Spanner · Sybase · CockroachDB · MongoDB
|
|
93
|
+
|
|
94
|
+
## Example workflow (any Prisma app)
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
$ cd my-nextjs-app
|
|
98
|
+
$ mostajs
|
|
99
|
+
|
|
100
|
+
Project : /path/to/my-nextjs-app
|
|
101
|
+
Manager : pnpm
|
|
102
|
+
Detected:
|
|
103
|
+
✓ Prisma schema (40 models)
|
|
104
|
+
⚠ entities.ts not generated
|
|
105
|
+
|
|
106
|
+
Choice [1]: 1 # Convert
|
|
107
|
+
entities : 40
|
|
108
|
+
warnings : 0
|
|
109
|
+
✓ Saved : .mostajs/generated/entities.ts
|
|
110
|
+
|
|
111
|
+
Choice [1]: 9 # Generate boilerplate
|
|
112
|
+
✓ Written : src/db.ts (Prisma bridge)
|
|
113
|
+
|
|
114
|
+
# now replace `new PrismaClient()` with `import { prisma } from './db.js'`
|
|
115
|
+
# ... your existing Prisma code runs on 13 databases
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Strategy
|
|
119
|
+
|
|
120
|
+
- **Schema conversion** : via [@mostajs/orm-adapter](https://www.npmjs.com/package/@mostajs/orm-adapter) — 4 adapters (Prisma, JSON Schema, OpenAPI, Native)
|
|
121
|
+
- **Runtime interception** : via [@mostajs/orm-bridge](https://www.npmjs.com/package/@mostajs/orm-bridge) — route Prisma calls to any of the 13 databases
|
|
122
|
+
- **Zero rewrite** : your existing `prisma.user.findMany()` stays unchanged
|
|
123
|
+
|
|
124
|
+
## Links
|
|
125
|
+
|
|
126
|
+
- npm : https://www.npmjs.com/package/@mostajs/orm-cli
|
|
127
|
+
- GitHub : https://github.com/apolocine/mosta-orm-cli
|
|
128
|
+
- Ecosystem : [@mostajs/orm](https://www.npmjs.com/package/@mostajs/orm), [@mostajs/orm-adapter](https://www.npmjs.com/package/@mostajs/orm-adapter), [@mostajs/orm-bridge](https://www.npmjs.com/package/@mostajs/orm-bridge)
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
**AGPL-3.0-or-later** + commercial license available.
|
|
133
|
+
|
|
134
|
+
For commercial use in closed-source projects : drmdh@msn.com
|
|
135
|
+
|
|
136
|
+
## Author
|
|
137
|
+
|
|
138
|
+
Dr Hamid MADANI <drmdh@msn.com>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// mostajs-launcher.cjs — cross-platform entry point for `mostajs` command
|
|
3
|
+
// Delegates to mostajs.sh on Unix, mostajs.bat on Windows.
|
|
4
|
+
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
|
|
10
|
+
const isWin = os.platform() === 'win32';
|
|
11
|
+
const binDir = __dirname;
|
|
12
|
+
const script = isWin
|
|
13
|
+
? path.join(binDir, 'mostajs.bat')
|
|
14
|
+
: path.join(binDir, 'mostajs.sh');
|
|
15
|
+
|
|
16
|
+
if (!fs.existsSync(script)) {
|
|
17
|
+
console.error(`[mostajs] launcher error: ${script} not found.`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Ensure executable on unix
|
|
22
|
+
if (!isWin) {
|
|
23
|
+
try { fs.chmodSync(script, 0o755); } catch { /* ignore */ }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const args = process.argv.slice(2);
|
|
27
|
+
const child = isWin
|
|
28
|
+
? spawn('cmd', ['/c', script, ...args], { stdio: 'inherit', cwd: process.cwd() })
|
|
29
|
+
: spawn('bash', [script, ...args], { stdio: 'inherit', cwd: process.cwd() });
|
|
30
|
+
|
|
31
|
+
child.on('exit', code => process.exit(code ?? 0));
|
|
32
|
+
child.on('error', err => {
|
|
33
|
+
console.error('[mostajs] launch failed:', err.message);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
});
|
package/bin/mostajs.bat
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
:: mostajs.bat — Universal interactive CLI for @mostajs/orm integration (Windows)
|
|
3
|
+
:: Author: Dr Hamid MADANI drmdh@msn.com
|
|
4
|
+
:: License: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
setlocal enabledelayedexpansion
|
|
7
|
+
|
|
8
|
+
set "CLI_VERSION=0.1.0"
|
|
9
|
+
set "PROJECT_ROOT=%cd%"
|
|
10
|
+
set "CONFIG_DIR=%PROJECT_ROOT%\.mostajs"
|
|
11
|
+
set "CONFIG_FILE=%CONFIG_DIR%\config.env"
|
|
12
|
+
set "LOG_DIR=%CONFIG_DIR%\logs"
|
|
13
|
+
set "GENERATED_DIR=%CONFIG_DIR%\generated"
|
|
14
|
+
|
|
15
|
+
if not exist "%CONFIG_DIR%" mkdir "%CONFIG_DIR%"
|
|
16
|
+
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%"
|
|
17
|
+
if not exist "%GENERATED_DIR%" mkdir "%GENERATED_DIR%"
|
|
18
|
+
|
|
19
|
+
:: ---------- CLI subcommands ----------
|
|
20
|
+
if "%~1"=="" goto INTERACTIVE
|
|
21
|
+
if /i "%~1"=="convert" goto SUB_CONVERT
|
|
22
|
+
if /i "%~1"=="detect" goto SUB_DETECT
|
|
23
|
+
if /i "%~1"=="health" goto ACTION_HEALTH
|
|
24
|
+
if /i "%~1"=="version" (echo mostajs %CLI_VERSION% & exit /b 0)
|
|
25
|
+
if /i "%~1"=="help" goto SHOW_HELP
|
|
26
|
+
echo Unknown command: %~1
|
|
27
|
+
exit /b 1
|
|
28
|
+
|
|
29
|
+
:SHOW_HELP
|
|
30
|
+
echo.
|
|
31
|
+
echo Usage:
|
|
32
|
+
echo mostajs Interactive menu
|
|
33
|
+
echo mostajs convert Run conversion
|
|
34
|
+
echo mostajs detect Print detected schemas
|
|
35
|
+
echo mostajs health Run health checks
|
|
36
|
+
echo mostajs version Print version
|
|
37
|
+
exit /b 0
|
|
38
|
+
|
|
39
|
+
:INTERACTIVE
|
|
40
|
+
|
|
41
|
+
:MAIN_MENU
|
|
42
|
+
cls
|
|
43
|
+
call :LOAD_ENV
|
|
44
|
+
call :DETECT_PROJECT
|
|
45
|
+
echo ============================================================
|
|
46
|
+
echo @mostajs/orm-cli v%CLI_VERSION% - Universal Schema Adapter
|
|
47
|
+
echo ============================================================
|
|
48
|
+
echo.
|
|
49
|
+
echo Project : %PROJECT_ROOT%
|
|
50
|
+
echo Manager : %PKG_MANAGER%
|
|
51
|
+
echo Detected:
|
|
52
|
+
if defined PRISMA_SCHEMA echo [OK] Prisma : !PRISMA_MODELS! models
|
|
53
|
+
if defined OPENAPI_FILE echo [OK] OpenAPI : !OPENAPI_FILE!
|
|
54
|
+
if exist "%GENERATED_DIR%\entities.ts" (
|
|
55
|
+
echo [OK] entities.ts generated
|
|
56
|
+
) else (
|
|
57
|
+
echo [!!] entities.ts not generated
|
|
58
|
+
)
|
|
59
|
+
echo.
|
|
60
|
+
echo ----- MAIN MENU -----
|
|
61
|
+
echo 1) Convert schema
|
|
62
|
+
echo 2) Configure database URIs
|
|
63
|
+
echo 3) Initialize dialects
|
|
64
|
+
echo 4) Tests menu
|
|
65
|
+
echo 5) Start services
|
|
66
|
+
echo 6) Metrics
|
|
67
|
+
echo 7) View logs
|
|
68
|
+
echo 8) Health checks
|
|
69
|
+
echo 9) Generate boilerplate
|
|
70
|
+
echo 0) About
|
|
71
|
+
echo Q) Quit
|
|
72
|
+
echo.
|
|
73
|
+
set /p "choice=Choice [1]: "
|
|
74
|
+
if "%choice%"=="" set "choice=1"
|
|
75
|
+
|
|
76
|
+
if /i "%choice%"=="1" goto ACTION_CONVERT
|
|
77
|
+
if /i "%choice%"=="2" goto MENU_DB
|
|
78
|
+
if /i "%choice%"=="3" goto ACTION_INIT
|
|
79
|
+
if /i "%choice%"=="4" goto MENU_TESTS
|
|
80
|
+
if /i "%choice%"=="5" goto MENU_SERVICES
|
|
81
|
+
if /i "%choice%"=="6" goto ACTION_METRICS
|
|
82
|
+
if /i "%choice%"=="7" goto ACTION_LOGS
|
|
83
|
+
if /i "%choice%"=="8" goto ACTION_HEALTH
|
|
84
|
+
if /i "%choice%"=="9" goto ACTION_BOILERPLATE
|
|
85
|
+
if /i "%choice%"=="0" goto ACTION_ABOUT
|
|
86
|
+
if /i "%choice%"=="q" goto END
|
|
87
|
+
goto MAIN_MENU
|
|
88
|
+
|
|
89
|
+
:: ============================================================
|
|
90
|
+
:: DETECT PROJECT
|
|
91
|
+
:: ============================================================
|
|
92
|
+
:DETECT_PROJECT
|
|
93
|
+
set "PRISMA_SCHEMA="
|
|
94
|
+
set "OPENAPI_FILE="
|
|
95
|
+
set "PRISMA_MODELS=0"
|
|
96
|
+
set "PKG_MANAGER=npm"
|
|
97
|
+
if exist "%PROJECT_ROOT%\pnpm-lock.yaml" set "PKG_MANAGER=pnpm"
|
|
98
|
+
if exist "%PROJECT_ROOT%\yarn.lock" set "PKG_MANAGER=yarn"
|
|
99
|
+
if exist "%PROJECT_ROOT%\prisma\schema.prisma" (
|
|
100
|
+
set "PRISMA_SCHEMA=%PROJECT_ROOT%\prisma\schema.prisma"
|
|
101
|
+
for /f %%A in ('findstr /c:"^model " "!PRISMA_SCHEMA!" 2^>nul ^| find /c /v ""') do set "PRISMA_MODELS=%%A"
|
|
102
|
+
)
|
|
103
|
+
for %%F in (openapi.yaml openapi.yml openapi.json api.yaml api.json) do (
|
|
104
|
+
if exist "%PROJECT_ROOT%\%%F" set "OPENAPI_FILE=%PROJECT_ROOT%\%%F"
|
|
105
|
+
)
|
|
106
|
+
exit /b 0
|
|
107
|
+
|
|
108
|
+
:: ============================================================
|
|
109
|
+
:: CONVERT
|
|
110
|
+
:: ============================================================
|
|
111
|
+
:ACTION_CONVERT
|
|
112
|
+
cls
|
|
113
|
+
call :DETECT_PROJECT
|
|
114
|
+
echo Converting schema -^> entities.ts
|
|
115
|
+
echo.
|
|
116
|
+
if defined PRISMA_SCHEMA (
|
|
117
|
+
set "INPUT_FILE=!PRISMA_SCHEMA!"
|
|
118
|
+
set "ADAPTER=PrismaAdapter"
|
|
119
|
+
set "IS_JSON=false"
|
|
120
|
+
) else if defined OPENAPI_FILE (
|
|
121
|
+
set "INPUT_FILE=!OPENAPI_FILE!"
|
|
122
|
+
set "ADAPTER=OpenApiAdapter"
|
|
123
|
+
set "IS_JSON=false"
|
|
124
|
+
) else (
|
|
125
|
+
echo [ERR] No schema detected.
|
|
126
|
+
pause
|
|
127
|
+
goto MAIN_MENU
|
|
128
|
+
)
|
|
129
|
+
echo Source : !INPUT_FILE!
|
|
130
|
+
echo Output : %GENERATED_DIR%\entities.ts
|
|
131
|
+
echo Adapter : !ADAPTER!
|
|
132
|
+
echo.
|
|
133
|
+
|
|
134
|
+
:: Check adapter installed
|
|
135
|
+
set "ADAPTER_PATH=%PROJECT_ROOT%\node_modules\@mostajs\orm-adapter\dist\index.js"
|
|
136
|
+
if not exist "!ADAPTER_PATH!" (
|
|
137
|
+
echo [!!] @mostajs/orm-adapter not installed in this project.
|
|
138
|
+
set /p "doit=Install now? [y/N]: "
|
|
139
|
+
if /i "!doit!"=="y" (
|
|
140
|
+
cd /d "%PROJECT_ROOT%"
|
|
141
|
+
call %PKG_MANAGER% install --save-dev @mostajs/orm-adapter @mostajs/orm
|
|
142
|
+
) else (
|
|
143
|
+
pause
|
|
144
|
+
goto MAIN_MENU
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
node --input-type=module -e "import { readFileSync, writeFileSync } from 'fs'; import { !ADAPTER! } from '%PROJECT_ROOT%/node_modules/@mostajs/orm-adapter/dist/index.js'; const src = readFileSync('!INPUT_FILE!','utf8'); const input = '!IS_JSON!' === 'true' ? JSON.parse(src) : src; const w=[]; const e = await new !ADAPTER!().toEntitySchema(input,{onWarning:x=>w.push(x)}); console.log('entities:', e.length, 'warnings:', w.length); writeFileSync('%GENERATED_DIR%/entities.ts','// Auto-generated by @mostajs/orm-cli v%CLI_VERSION%\nimport type { EntitySchema } from \"@mostajs/orm\";\nexport const entities: EntitySchema[] = '+JSON.stringify(e,null,2)+';\nexport const entityByName = Object.fromEntries(entities.map(x=>[x.name,x]));\n');" > "%LOG_DIR%\convert.log" 2>&1
|
|
149
|
+
type "%LOG_DIR%\convert.log"
|
|
150
|
+
pause
|
|
151
|
+
goto MAIN_MENU
|
|
152
|
+
|
|
153
|
+
:SUB_CONVERT
|
|
154
|
+
call :DETECT_PROJECT
|
|
155
|
+
goto ACTION_CONVERT
|
|
156
|
+
|
|
157
|
+
:SUB_DETECT
|
|
158
|
+
call :DETECT_PROJECT
|
|
159
|
+
echo project : %PROJECT_ROOT%
|
|
160
|
+
echo manager : %PKG_MANAGER%
|
|
161
|
+
if defined PRISMA_SCHEMA echo prisma : %PRISMA_SCHEMA% (%PRISMA_MODELS% models)
|
|
162
|
+
if defined OPENAPI_FILE echo openapi : %OPENAPI_FILE%
|
|
163
|
+
exit /b 0
|
|
164
|
+
|
|
165
|
+
:: ============================================================
|
|
166
|
+
:: MENU 2 : DATABASES
|
|
167
|
+
:: ============================================================
|
|
168
|
+
:MENU_DB
|
|
169
|
+
cls
|
|
170
|
+
call :LOAD_ENV
|
|
171
|
+
echo ==== Database configuration ====
|
|
172
|
+
echo 1) MongoDB : %MONGODB_URI%
|
|
173
|
+
echo 2) PostgreSQL : %POSTGRES_URI%
|
|
174
|
+
echo 3) MySQL/MariaDB : %MYSQL_URI%
|
|
175
|
+
echo 4) SQLite : %SQLITE_URI%
|
|
176
|
+
echo 5) Oracle : %ORACLE_URI%
|
|
177
|
+
echo 6) MSSQL : %MSSQL_URI%
|
|
178
|
+
echo 7) DB2 : %DB2_URI%
|
|
179
|
+
echo P) App port : %APP_PORT%
|
|
180
|
+
echo N) mosta-net port : %MOSTA_NET_PORT%
|
|
181
|
+
echo R) Reset config
|
|
182
|
+
echo B) Back
|
|
183
|
+
echo.
|
|
184
|
+
set /p "choice=Choice: "
|
|
185
|
+
if /i "%choice%"=="1" set /p "v=MongoDB URI: " & call :SAVE_ENV MONGODB_URI "!v!" & goto MENU_DB
|
|
186
|
+
if /i "%choice%"=="2" set /p "v=PostgreSQL URI: " & call :SAVE_ENV POSTGRES_URI "!v!" & goto MENU_DB
|
|
187
|
+
if /i "%choice%"=="3" set /p "v=MySQL URI: " & call :SAVE_ENV MYSQL_URI "!v!" & goto MENU_DB
|
|
188
|
+
if /i "%choice%"=="4" set /p "v=SQLite path: " & call :SAVE_ENV SQLITE_URI "!v!" & goto MENU_DB
|
|
189
|
+
if /i "%choice%"=="5" set /p "v=Oracle URI: " & call :SAVE_ENV ORACLE_URI "!v!" & goto MENU_DB
|
|
190
|
+
if /i "%choice%"=="6" set /p "v=MSSQL URI: " & call :SAVE_ENV MSSQL_URI "!v!" & goto MENU_DB
|
|
191
|
+
if /i "%choice%"=="7" set /p "v=DB2 URI: " & call :SAVE_ENV DB2_URI "!v!" & goto MENU_DB
|
|
192
|
+
if /i "%choice%"=="p" set /p "v=App port: " & call :SAVE_ENV APP_PORT "!v!" & goto MENU_DB
|
|
193
|
+
if /i "%choice%"=="n" set /p "v=mosta-net port: " & call :SAVE_ENV MOSTA_NET_PORT "!v!" & goto MENU_DB
|
|
194
|
+
if /i "%choice%"=="r" del "%CONFIG_FILE%" 2>nul & goto MENU_DB
|
|
195
|
+
if /i "%choice%"=="b" goto MAIN_MENU
|
|
196
|
+
goto MENU_DB
|
|
197
|
+
|
|
198
|
+
:: ============================================================
|
|
199
|
+
:: ACTION 3 : INIT
|
|
200
|
+
:: ============================================================
|
|
201
|
+
:ACTION_INIT
|
|
202
|
+
cls
|
|
203
|
+
call :LOAD_ENV
|
|
204
|
+
if not exist "%GENERATED_DIR%\entities.ts" (
|
|
205
|
+
echo [ERR] Run conversion (menu 1) first.
|
|
206
|
+
pause
|
|
207
|
+
goto MAIN_MENU
|
|
208
|
+
)
|
|
209
|
+
echo Will initialize dialects for:
|
|
210
|
+
if defined MONGODB_URI echo - mongodb
|
|
211
|
+
if defined POSTGRES_URI echo - postgres
|
|
212
|
+
if defined MYSQL_URI echo - mysql
|
|
213
|
+
if defined SQLITE_URI echo - sqlite
|
|
214
|
+
if defined ORACLE_URI echo - oracle
|
|
215
|
+
echo.
|
|
216
|
+
set /p "go=Proceed? [y/N]: "
|
|
217
|
+
if /i not "!go!"=="y" goto MAIN_MENU
|
|
218
|
+
node "%GENERATED_DIR%\..\init-all.mjs" > "%LOG_DIR%\init.log" 2>&1
|
|
219
|
+
type "%LOG_DIR%\init.log"
|
|
220
|
+
pause
|
|
221
|
+
goto MAIN_MENU
|
|
222
|
+
|
|
223
|
+
:: ============================================================
|
|
224
|
+
:: MENU 4 : TESTS
|
|
225
|
+
:: ============================================================
|
|
226
|
+
:MENU_TESTS
|
|
227
|
+
cls
|
|
228
|
+
call :LOAD_ENV
|
|
229
|
+
echo ==== Tests menu ====
|
|
230
|
+
echo 1) Open app in browser
|
|
231
|
+
echo 2) Open mosta-net dashboard
|
|
232
|
+
echo 3) Mobile URL (QR if qrencode installed)
|
|
233
|
+
echo 4) MCP endpoint config (Claude/GPT)
|
|
234
|
+
echo 5) curl smoke test
|
|
235
|
+
echo 6) Playwright
|
|
236
|
+
echo B) Back
|
|
237
|
+
echo.
|
|
238
|
+
set /p "choice=Choice [1]: "
|
|
239
|
+
if "%choice%"=="" set "choice=1"
|
|
240
|
+
if /i "%choice%"=="1" start "" "http://localhost:%APP_PORT%" & goto MENU_TESTS
|
|
241
|
+
if /i "%choice%"=="2" start "" "http://localhost:%MOSTA_NET_PORT%" & goto MENU_TESTS
|
|
242
|
+
if /i "%choice%"=="3" goto ACTION_QR
|
|
243
|
+
if /i "%choice%"=="4" goto ACTION_MCP
|
|
244
|
+
if /i "%choice%"=="5" goto ACTION_CURL
|
|
245
|
+
if /i "%choice%"=="6" cd /d "%PROJECT_ROOT%" & call npx playwright test & pause & goto MENU_TESTS
|
|
246
|
+
if /i "%choice%"=="b" goto MAIN_MENU
|
|
247
|
+
goto MENU_TESTS
|
|
248
|
+
|
|
249
|
+
:ACTION_QR
|
|
250
|
+
cls
|
|
251
|
+
for /f "tokens=14" %%A in ('ipconfig ^| findstr /i "IPv4" ^| findstr /v "169.254"') do set "LOCAL_IP=%%A"
|
|
252
|
+
if not defined LOCAL_IP set "LOCAL_IP=localhost"
|
|
253
|
+
set "URL=http://!LOCAL_IP!:%APP_PORT%"
|
|
254
|
+
echo Mobile URL : !URL!
|
|
255
|
+
echo.
|
|
256
|
+
where qrencode >nul 2>nul
|
|
257
|
+
if not errorlevel 1 (qrencode -t ANSIUTF8 "!URL!") else (echo Install qrencode for QR generation)
|
|
258
|
+
pause
|
|
259
|
+
goto MENU_TESTS
|
|
260
|
+
|
|
261
|
+
:ACTION_MCP
|
|
262
|
+
cls
|
|
263
|
+
set "MCP_URL=http://localhost:%MOSTA_NET_PORT%/mcp"
|
|
264
|
+
echo MCP endpoint : !MCP_URL!
|
|
265
|
+
echo.
|
|
266
|
+
echo Claude Desktop config:
|
|
267
|
+
echo {
|
|
268
|
+
echo "mcpServers": {
|
|
269
|
+
for %%A in ("%PROJECT_ROOT%") do echo "%%~nA": { "url": "!MCP_URL!" }
|
|
270
|
+
echo }
|
|
271
|
+
echo }
|
|
272
|
+
pause
|
|
273
|
+
goto MENU_TESTS
|
|
274
|
+
|
|
275
|
+
:ACTION_CURL
|
|
276
|
+
cls
|
|
277
|
+
for %%U in ("http://localhost:%APP_PORT%/" "http://localhost:%APP_PORT%/api/health" "http://localhost:%MOSTA_NET_PORT%/" "http://localhost:%MOSTA_NET_PORT%/mcp") do (
|
|
278
|
+
echo GET %%~U
|
|
279
|
+
curl -s -o nul -w " status=%%{http_code} time=%%{time_total}s\n" --max-time 5 %%U
|
|
280
|
+
)
|
|
281
|
+
pause
|
|
282
|
+
goto MENU_TESTS
|
|
283
|
+
|
|
284
|
+
:: ============================================================
|
|
285
|
+
:: MENU 5 : SERVICES
|
|
286
|
+
:: ============================================================
|
|
287
|
+
:MENU_SERVICES
|
|
288
|
+
cls
|
|
289
|
+
call :LOAD_ENV
|
|
290
|
+
echo ==== Services ====
|
|
291
|
+
echo 1) Start dev server (new window)
|
|
292
|
+
echo 2) Show URLs
|
|
293
|
+
echo B) Back
|
|
294
|
+
echo.
|
|
295
|
+
set /p "choice=Choice [1]: "
|
|
296
|
+
if "%choice%"=="" set "choice=1"
|
|
297
|
+
if /i "%choice%"=="1" (
|
|
298
|
+
cd /d "%PROJECT_ROOT%"
|
|
299
|
+
start "dev" cmd /k "%PKG_MANAGER% run dev"
|
|
300
|
+
call :SHOW_URLS
|
|
301
|
+
pause
|
|
302
|
+
goto MENU_SERVICES
|
|
303
|
+
)
|
|
304
|
+
if /i "%choice%"=="2" call :SHOW_URLS & pause & goto MENU_SERVICES
|
|
305
|
+
if /i "%choice%"=="b" goto MAIN_MENU
|
|
306
|
+
goto MENU_SERVICES
|
|
307
|
+
|
|
308
|
+
:SHOW_URLS
|
|
309
|
+
echo.
|
|
310
|
+
echo Access URLs:
|
|
311
|
+
echo App (local) : http://localhost:%APP_PORT%
|
|
312
|
+
echo mosta-net : http://localhost:%MOSTA_NET_PORT%
|
|
313
|
+
echo MCP endpoint (AI) : http://localhost:%MOSTA_NET_PORT%/mcp
|
|
314
|
+
exit /b 0
|
|
315
|
+
|
|
316
|
+
:: ============================================================
|
|
317
|
+
:: ACTION 6 : METRICS
|
|
318
|
+
:: ============================================================
|
|
319
|
+
:ACTION_METRICS
|
|
320
|
+
cls
|
|
321
|
+
call :DETECT_PROJECT
|
|
322
|
+
echo ==== Metrics ====
|
|
323
|
+
if defined PRISMA_SCHEMA echo Prisma models : !PRISMA_MODELS!
|
|
324
|
+
if exist "%GENERATED_DIR%\entities.ts" (
|
|
325
|
+
for %%A in ("%GENERATED_DIR%\entities.ts") do echo entities.ts : %%~zA bytes
|
|
326
|
+
)
|
|
327
|
+
pause
|
|
328
|
+
goto MAIN_MENU
|
|
329
|
+
|
|
330
|
+
:: ============================================================
|
|
331
|
+
:: ACTION 7 : LOGS
|
|
332
|
+
:: ============================================================
|
|
333
|
+
:ACTION_LOGS
|
|
334
|
+
cls
|
|
335
|
+
echo ==== Logs ====
|
|
336
|
+
set "i=0"
|
|
337
|
+
for %%A in ("%LOG_DIR%\*.log") do (
|
|
338
|
+
set /a "i+=1"
|
|
339
|
+
echo !i!^) %%~nxA
|
|
340
|
+
set "LOG_!i!=%%A"
|
|
341
|
+
)
|
|
342
|
+
if %i%==0 (echo No logs yet & pause & goto MAIN_MENU)
|
|
343
|
+
set /p "c=File #: "
|
|
344
|
+
if defined LOG_%c% (call set "F=%%LOG_%c%%%" & type "!F!")
|
|
345
|
+
pause
|
|
346
|
+
goto MAIN_MENU
|
|
347
|
+
|
|
348
|
+
:: ============================================================
|
|
349
|
+
:: ACTION 8 : HEALTH
|
|
350
|
+
:: ============================================================
|
|
351
|
+
:ACTION_HEALTH
|
|
352
|
+
cls
|
|
353
|
+
call :DETECT_PROJECT
|
|
354
|
+
echo ==== Health checks ====
|
|
355
|
+
where node >nul 2>nul && (echo [OK] node) || (echo [ERR] node missing)
|
|
356
|
+
where %PKG_MANAGER% >nul 2>nul && (echo [OK] %PKG_MANAGER%) || (echo [ERR] %PKG_MANAGER% missing)
|
|
357
|
+
if exist "%PROJECT_ROOT%\package.json" (echo [OK] package.json) else (echo [!!] package.json missing)
|
|
358
|
+
if defined PRISMA_SCHEMA (echo [OK] Prisma schema ^(!PRISMA_MODELS! models^)) else (echo [!!] no Prisma schema)
|
|
359
|
+
if defined OPENAPI_FILE (echo [OK] OpenAPI file) else (echo [!!] no OpenAPI)
|
|
360
|
+
if exist "%GENERATED_DIR%\entities.ts" (echo [OK] entities generated) else (echo [!!] not generated)
|
|
361
|
+
where curl >nul 2>nul && (echo [OK] curl) || (echo [!!] curl missing)
|
|
362
|
+
where qrencode >nul 2>nul && (echo [OK] qrencode) || (echo [!!] qrencode optional - missing)
|
|
363
|
+
pause
|
|
364
|
+
goto MAIN_MENU
|
|
365
|
+
|
|
366
|
+
:: ============================================================
|
|
367
|
+
:: ACTION 9 : BOILERPLATE
|
|
368
|
+
:: ============================================================
|
|
369
|
+
:ACTION_BOILERPLATE
|
|
370
|
+
cls
|
|
371
|
+
echo ==== Boilerplate ====
|
|
372
|
+
echo 1) src\db.ts (Prisma bridge wrapper)
|
|
373
|
+
echo 2) src\mosta-orm.ts (direct usage)
|
|
374
|
+
echo 3) .env.example
|
|
375
|
+
echo.
|
|
376
|
+
set /p "c=Choice [1]: "
|
|
377
|
+
if "%c%"=="" set "c=1"
|
|
378
|
+
if "%c%"=="1" goto GEN_BRIDGE
|
|
379
|
+
if "%c%"=="2" goto GEN_DIRECT
|
|
380
|
+
if "%c%"=="3" goto GEN_ENV
|
|
381
|
+
goto MAIN_MENU
|
|
382
|
+
|
|
383
|
+
:GEN_BRIDGE
|
|
384
|
+
if not exist "%PROJECT_ROOT%\src" mkdir "%PROJECT_ROOT%\src"
|
|
385
|
+
(
|
|
386
|
+
echo // Auto-generated by @mostajs/orm-cli
|
|
387
|
+
echo import { PrismaClient } from '@prisma/client';
|
|
388
|
+
echo import { mostaExtension } from '@mostajs/orm-bridge/prisma';
|
|
389
|
+
echo import { entityByName } from '../.mostajs/generated/entities.js';
|
|
390
|
+
echo.
|
|
391
|
+
echo export const prisma = new PrismaClient^(^).$extends^(mostaExtension^({
|
|
392
|
+
echo models: {
|
|
393
|
+
echo // AuditLog: { dialect: 'mongodb', url: process.env.MONGODB_URI!, schema: entityByName.AuditLog },
|
|
394
|
+
echo },
|
|
395
|
+
echo fallback: 'source',
|
|
396
|
+
echo }^)^);
|
|
397
|
+
) > "%PROJECT_ROOT%\src\db.ts"
|
|
398
|
+
echo [OK] Written src\db.ts
|
|
399
|
+
pause
|
|
400
|
+
goto MAIN_MENU
|
|
401
|
+
|
|
402
|
+
:GEN_DIRECT
|
|
403
|
+
if not exist "%PROJECT_ROOT%\src" mkdir "%PROJECT_ROOT%\src"
|
|
404
|
+
(
|
|
405
|
+
echo // Auto-generated by @mostajs/orm-cli
|
|
406
|
+
echo import { getDialect } from '@mostajs/orm';
|
|
407
|
+
echo import { entities } from '../.mostajs/generated/entities.js';
|
|
408
|
+
echo.
|
|
409
|
+
echo export async function createOrm^(^) {
|
|
410
|
+
echo const dialect = await getDialect^({ dialect: 'postgres', uri: process.env.DATABASE_URL! }^);
|
|
411
|
+
echo await dialect.initSchema^(entities^);
|
|
412
|
+
echo return { dialect, entities };
|
|
413
|
+
echo }
|
|
414
|
+
) > "%PROJECT_ROOT%\src\mosta-orm.ts"
|
|
415
|
+
echo [OK] Written src\mosta-orm.ts
|
|
416
|
+
pause
|
|
417
|
+
goto MAIN_MENU
|
|
418
|
+
|
|
419
|
+
:GEN_ENV
|
|
420
|
+
(
|
|
421
|
+
echo MONGODB_URI=mongodb://localhost:27017/app
|
|
422
|
+
echo POSTGRES_URI=postgres://user:pw@localhost:5432/app
|
|
423
|
+
echo MYSQL_URI=mysql://user:pw@localhost:3306/app
|
|
424
|
+
echo APP_PORT=3000
|
|
425
|
+
echo MOSTA_NET_PORT=4447
|
|
426
|
+
) > "%PROJECT_ROOT%\.env.example"
|
|
427
|
+
echo [OK] Written .env.example
|
|
428
|
+
pause
|
|
429
|
+
goto MAIN_MENU
|
|
430
|
+
|
|
431
|
+
:: ============================================================
|
|
432
|
+
:: ACTION 0 : ABOUT
|
|
433
|
+
:: ============================================================
|
|
434
|
+
:ACTION_ABOUT
|
|
435
|
+
cls
|
|
436
|
+
echo ============================================================
|
|
437
|
+
echo mostajs-cli v%CLI_VERSION%
|
|
438
|
+
echo ============================================================
|
|
439
|
+
echo.
|
|
440
|
+
echo Convert schemas to @mostajs/orm EntitySchema[]
|
|
441
|
+
echo Gain access to 13 databases without rewriting code.
|
|
442
|
+
echo.
|
|
443
|
+
echo Inputs : Prisma, OpenAPI, JSON Schema
|
|
444
|
+
echo DBs : PostgreSQL, MySQL, MariaDB, SQLite, MSSQL, Oracle,
|
|
445
|
+
echo DB2, CockroachDB, HANA, HSQLDB, Spanner, Sybase, MongoDB
|
|
446
|
+
echo.
|
|
447
|
+
echo Packages:
|
|
448
|
+
echo @mostajs/orm
|
|
449
|
+
echo @mostajs/orm-adapter
|
|
450
|
+
echo @mostajs/orm-bridge
|
|
451
|
+
echo.
|
|
452
|
+
echo Author : Dr Hamid MADANI ^<drmdh@msn.com^>
|
|
453
|
+
echo License : AGPL-3.0-or-later
|
|
454
|
+
pause
|
|
455
|
+
goto MAIN_MENU
|
|
456
|
+
|
|
457
|
+
:: ============================================================
|
|
458
|
+
:: HELPERS
|
|
459
|
+
:: ============================================================
|
|
460
|
+
:LOAD_ENV
|
|
461
|
+
set "MONGODB_URI="
|
|
462
|
+
set "POSTGRES_URI="
|
|
463
|
+
set "MYSQL_URI="
|
|
464
|
+
set "SQLITE_URI="
|
|
465
|
+
set "ORACLE_URI="
|
|
466
|
+
set "MSSQL_URI="
|
|
467
|
+
set "DB2_URI="
|
|
468
|
+
set "APP_PORT=3000"
|
|
469
|
+
set "MOSTA_NET_PORT=4447"
|
|
470
|
+
if exist "%CONFIG_FILE%" (
|
|
471
|
+
for /f "tokens=1,* delims==" %%A in ('type "%CONFIG_FILE%"') do set "%%A=%%B"
|
|
472
|
+
)
|
|
473
|
+
exit /b 0
|
|
474
|
+
|
|
475
|
+
:SAVE_ENV
|
|
476
|
+
set "KEY=%~1"
|
|
477
|
+
set "VAL=%~2"
|
|
478
|
+
if not exist "%CONFIG_FILE%" (
|
|
479
|
+
echo %KEY%=%VAL%> "%CONFIG_FILE%"
|
|
480
|
+
) else (
|
|
481
|
+
findstr /v "^%KEY%=" "%CONFIG_FILE%" > "%CONFIG_FILE%.tmp" 2>nul
|
|
482
|
+
echo %KEY%=%VAL%>> "%CONFIG_FILE%.tmp"
|
|
483
|
+
move /y "%CONFIG_FILE%.tmp" "%CONFIG_FILE%" >nul
|
|
484
|
+
)
|
|
485
|
+
echo [OK] Saved %KEY%
|
|
486
|
+
exit /b 0
|
|
487
|
+
|
|
488
|
+
:END
|
|
489
|
+
endlocal
|
|
490
|
+
exit /b 0
|