@mostajs/orm-cli 0.3.2 → 0.4.1

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.
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env node
2
+ // install-bridge.mjs — one-shot codemod : scan a Prisma project, find every
3
+ // file that instantiates PrismaClient, and rewrite it to use
4
+ // createPrismaLikeDb() from @mostajs/orm-bridge.
5
+ //
6
+ // Author: Dr Hamid MADANI drmdh@msn.com
7
+ // License: AGPL-3.0-or-later
8
+ //
9
+ // Usage (invoked by bin/mostajs.sh as `mostajs install-bridge`) :
10
+ //
11
+ // node install-bridge.mjs # dry-run (default, safe)
12
+ // node install-bridge.mjs --apply # actually write files
13
+ // node install-bridge.mjs --file X # restrict to a single file
14
+ // node install-bridge.mjs --project P # root to scan (default: cwd)
15
+ // node install-bridge.mjs --restore # restore from .prisma.bak backups
16
+ //
17
+ // The rewriter is deliberately conservative :
18
+ // - It only touches files that CREATE a PrismaClient (`new PrismaClient(...)`).
19
+ // - It preserves the original export name (`prisma`, `db`, `client`, `default`)
20
+ // so none of the 10 to 10000 call-sites elsewhere in the codebase need to change.
21
+ // - Original file is saved as <path>.prisma.bak (never overwritten).
22
+ // - Re-runs are idempotent : if the file already uses createPrismaLikeDb,
23
+ // the codemod skips it.
24
+
25
+ import { readFileSync, writeFileSync, readdirSync, statSync, existsSync, renameSync, copyFileSync } from 'node:fs';
26
+ import { join, resolve, relative, extname } from 'node:path';
27
+
28
+ // ---------- CLI ----------
29
+ const argv = process.argv.slice(2);
30
+ const flag = (name) => argv.includes(`--${name}`);
31
+ const val = (name) => { const i = argv.indexOf(`--${name}`); return i >= 0 ? argv[i + 1] : null; };
32
+
33
+ const APPLY = flag('apply');
34
+ const RESTORE = flag('restore');
35
+ const ONE_FILE = val('file');
36
+ const ROOT = resolve(val('project') ?? process.cwd());
37
+ const QUIET = flag('quiet');
38
+
39
+ const log = (...a) => { if (!QUIET) console.log(...a); };
40
+ const c = { cyan: s => `\x1b[36m${s}\x1b[0m`, yellow: s => `\x1b[33m${s}\x1b[0m`, green: s => `\x1b[32m${s}\x1b[0m`, red: s => `\x1b[31m${s}\x1b[0m`, bold: s => `\x1b[1m${s}\x1b[0m`, dim: s => `\x1b[2m${s}\x1b[0m` };
41
+
42
+ // ---------- Walk ----------
43
+ const SKIP_DIRS = new Set(['node_modules', '.next', '.svelte-kit', 'dist', 'build', '.turbo', '.vercel', '.cache', 'coverage', '.git', '.vscode', '.idea']);
44
+ const EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.js', '.jsx', '.mjs']);
45
+
46
+ function* walk(dir) {
47
+ let entries;
48
+ try { entries = readdirSync(dir); } catch { return; }
49
+ for (const name of entries) {
50
+ if (SKIP_DIRS.has(name)) continue;
51
+ const p = join(dir, name);
52
+ let st;
53
+ try { st = statSync(p); } catch { continue; }
54
+ if (st.isDirectory()) yield* walk(p);
55
+ else if (EXTENSIONS.has(extname(name))) yield p;
56
+ }
57
+ }
58
+
59
+ // ---------- Detection ----------
60
+ // Patterns we consider "PrismaClient instantiation sites"
61
+ const RX_IMPORT = /import\s*(?:\{[^}]*PrismaClient[^}]*\}|[^;]*?)\s*from\s*['"]@prisma\/client['"]/;
62
+ const RX_NEW = /new\s+PrismaClient\s*\(/;
63
+ const RX_ALREADY = /@mostajs\/orm-bridge\/prisma-client/;
64
+
65
+ // Detect the export shape to preserve the name the codebase depends on.
66
+ // export const db = new PrismaClient(...) → named, "db"
67
+ // export const prisma = new PrismaClient(...) → named, "prisma"
68
+ // export default new PrismaClient(...) → default
69
+ // const prisma = ...; export { prisma } → named, "prisma"
70
+ function detectExportShape(source) {
71
+ // Singleton pattern commonly used in Next.js :
72
+ // const g = globalThis as ... { prisma: ... }
73
+ // export const db = g.prisma ?? new PrismaClient()
74
+ const mNamed = source.match(/export\s+const\s+(\w+)\s*=\s*(?:[^;]*?)\bnew\s+PrismaClient/);
75
+ if (mNamed) return { kind: 'const', name: mNamed[1] };
76
+
77
+ const mLet = source.match(/export\s+let\s+(\w+)\s*=\s*(?:[^;]*?)\bnew\s+PrismaClient/);
78
+ if (mLet) return { kind: 'let', name: mLet[1] };
79
+
80
+ const mDefault = source.match(/export\s+default\s+(?:[^;]*?)\bnew\s+PrismaClient/);
81
+ if (mDefault) return { kind: 'default', name: null };
82
+
83
+ // Bare global : const prisma = new PrismaClient(); followed somewhere by `export { prisma }` or not
84
+ const mBare = source.match(/(?:^|\n)\s*(?:const|let)\s+(\w+)\s*=\s*(?:[^;]*?)\bnew\s+PrismaClient/);
85
+ if (mBare) {
86
+ const name = mBare[1];
87
+ if (new RegExp(`export\\s*\\{[^}]*\\b${name}\\b[^}]*\\}`).test(source)) {
88
+ return { kind: 'export-block', name };
89
+ }
90
+ return { kind: 'const', name }; // assume user wants to export it ; safer default
91
+ }
92
+
93
+ return null;
94
+ }
95
+
96
+ // ---------- Rewrite ----------
97
+ function buildReplacement(shape) {
98
+ const header = `// Auto-generated by \`mostajs install-bridge\` on ${new Date().toISOString()}\n// Original file backed up as <this-file>.prisma.bak\n// Every db/prisma/client call is now routed to @mostajs/orm (13 dialects).\nimport 'server-only'\nimport { createPrismaLikeDb } from '@mostajs/orm-bridge/prisma-client'\n`;
99
+ if (shape.kind === 'default') {
100
+ return `${header}\nexport default createPrismaLikeDb()\n`;
101
+ }
102
+ const kw = shape.kind === 'let' ? 'let' : 'const';
103
+ if (shape.kind === 'export-block') {
104
+ return `${header}\n${kw} ${shape.name} = createPrismaLikeDb()\nexport { ${shape.name} }\n`;
105
+ }
106
+ return `${header}\nexport ${kw} ${shape.name} = createPrismaLikeDb()\n`;
107
+ }
108
+
109
+ // ---------- Restore ----------
110
+ function restoreBackups() {
111
+ const restored = [];
112
+ for (const p of walk(ROOT)) {
113
+ if (!p.endsWith('.prisma.bak')) continue;
114
+ const original = p.slice(0, -'.prisma.bak'.length);
115
+ if (APPLY) {
116
+ renameSync(p, original);
117
+ log(` ${c.green('✓')} restored ${c.dim(relative(ROOT, original))}`);
118
+ } else {
119
+ log(` ${c.yellow('•')} would restore ${c.dim(relative(ROOT, original))}`);
120
+ }
121
+ restored.push(original);
122
+ }
123
+ return restored;
124
+ }
125
+
126
+ // ---------- Main ----------
127
+ if (RESTORE) {
128
+ log(c.bold('▶ Restoring .prisma.bak files' + (APPLY ? '' : c.yellow(' (dry-run, use --apply)'))));
129
+ const r = restoreBackups();
130
+ log(`\n${r.length} file(s) ${APPLY ? 'restored' : 'would be restored'}`);
131
+ process.exit(0);
132
+ }
133
+
134
+ log(c.bold(`▶ mostajs install-bridge — scanning ${c.cyan(ROOT)}`));
135
+ log('');
136
+
137
+ const candidates = [];
138
+ const iter = ONE_FILE ? [resolve(ROOT, ONE_FILE)] : walk(ROOT);
139
+ for (const p of iter) {
140
+ let src;
141
+ try { src = readFileSync(p, 'utf8'); } catch { continue; }
142
+ if (!RX_IMPORT.test(src) && !RX_NEW.test(src)) continue;
143
+ if (RX_ALREADY.test(src)) {
144
+ log(` ${c.dim('— skip (already bridged) ' + relative(ROOT, p))}`);
145
+ continue;
146
+ }
147
+ if (!RX_NEW.test(src)) continue; // imports only = not an instantiation site
148
+ const shape = detectExportShape(src);
149
+ if (!shape) {
150
+ log(` ${c.yellow('?')} ${relative(ROOT, p)} — PrismaClient detected but export shape unknown, skipping`);
151
+ continue;
152
+ }
153
+ candidates.push({ path: p, rel: relative(ROOT, p), shape, src });
154
+ }
155
+
156
+ if (candidates.length === 0) {
157
+ log(c.yellow(' No instantiation sites found.'));
158
+ log('');
159
+ log(` Did you remove \`new PrismaClient()\` already ? The bridge may already be in place.`);
160
+ log(` Re-scan with: ${c.cyan('mostajs install-bridge --restore --apply')} to undo a prior run.`);
161
+ process.exit(0);
162
+ }
163
+
164
+ log(c.bold(`Found ${candidates.length} PrismaClient instantiation site(s):`));
165
+ for (const ca of candidates) {
166
+ log(` ${c.green('→')} ${ca.rel} ${c.dim(`(${ca.shape.kind}${ca.shape.name ? ' ' + ca.shape.name : ''})`)}`);
167
+ }
168
+ log('');
169
+
170
+ if (!APPLY) {
171
+ log(c.yellow('Dry-run — no files written. Re-run with --apply to execute.'));
172
+ log('');
173
+ log(c.bold('Preview of rewrite for the first file :'));
174
+ log(c.dim('─────────────────────────────────────────'));
175
+ log(buildReplacement(candidates[0].shape));
176
+ log(c.dim('─────────────────────────────────────────'));
177
+ process.exit(0);
178
+ }
179
+
180
+ // ---------- Apply ----------
181
+ log(c.bold('Applying rewrites :'));
182
+ for (const ca of candidates) {
183
+ const bak = ca.path + '.prisma.bak';
184
+ if (!existsSync(bak)) copyFileSync(ca.path, bak);
185
+ writeFileSync(ca.path, buildReplacement(ca.shape));
186
+ log(` ${c.green('✓')} rewrote ${ca.rel} ${c.dim(`(backup: ${relative(ROOT, bak)})`)}`);
187
+ }
188
+
189
+ log('');
190
+ log(c.bold(c.green(`✓ Bridge installed in ${candidates.length} file(s).`)));
191
+ log('');
192
+ log('Next steps :');
193
+ log(` 1. ${c.cyan('npm i @mostajs/orm @mostajs/orm-bridge server-only --legacy-peer-deps')}`);
194
+ log(` 2. ${c.cyan('npx @mostajs/orm-cli')} → menu 1 (Convert Prisma → entities.json) → menu 3 (init DDL)`);
195
+ log(` 3. Set ${c.cyan('DB_DIALECT')} + ${c.cyan('SGBD_URI')} in .env (or: menu 2 → i to import)`);
196
+ log(` 4. ${c.cyan('npm run dev')} and test.`);
197
+ log('');
198
+ log(`To undo : ${c.cyan('mostajs install-bridge --restore --apply')}`);
package/bin/mostajs.sh CHANGED
@@ -438,6 +438,8 @@ menu_main() {
438
438
  echo -e " ${CYAN}8${RESET}) Health checks"
439
439
  echo -e " ${CYAN}9${RESET}) Generate boilerplate (src/db.ts with bridge)"
440
440
  echo -e " ${CYAN}s${RESET}) ${BOLD}Seeding${RESET} (upload / validate / apply seed data)"
441
+ echo -e " ${GREEN}b${RESET}) ${BOLD}Bootstrap${RESET} — one-shot migration of a Prisma project"
442
+ echo -e " ${GREEN}i${RESET}) ${BOLD}Install bridge${RESET} — codemod PrismaClient → bridge (dry-run / apply / restore)"
441
443
  echo -e " ${CYAN}0${RESET}) About / Help"
442
444
  echo
443
445
  echo -e " ${RED}q${RESET}) Quit"
@@ -455,12 +457,63 @@ menu_main() {
455
457
  8) action_healthcheck ;;
456
458
  9) action_generate_boilerplate ;;
457
459
  s|S) menu_seeding ;;
460
+ b|B) menu_bootstrap ;;
461
+ i|I) menu_install_bridge ;;
458
462
  0) action_about ;;
459
463
  q|Q) exit 0 ;;
460
464
  *) warn "Unknown choice"; pause ;;
461
465
  esac
462
466
  }
463
467
 
468
+ # ------------------------------------------------------------
469
+ # Interactive wrapper for `install-bridge` codemod
470
+ # ------------------------------------------------------------
471
+ menu_install_bridge() {
472
+ header
473
+ echo -e "${BOLD}${MAGENTA}▶ Install bridge — PrismaClient codemod${RESET}"
474
+ echo
475
+ echo " ${CYAN}1${RESET}) Dry-run : list files that would be rewritten (default)"
476
+ echo " ${CYAN}2${RESET}) Apply : rewrite PrismaClient sites to createPrismaLikeDb()"
477
+ echo " ${CYAN}3${RESET}) Restore : revert .prisma.bak files (dry-run)"
478
+ echo " ${CYAN}4${RESET}) Restore : revert .prisma.bak files (apply)"
479
+ echo " ${RED}0${RESET}) Back"
480
+ echo
481
+ local cli_dir
482
+ cli_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
483
+ local choice; choice=$(ask "Choice" "1")
484
+ case "$choice" in
485
+ 1) node "$cli_dir/bin/install-bridge.mjs" ;;
486
+ 2) node "$cli_dir/bin/install-bridge.mjs" --apply ;;
487
+ 3) node "$cli_dir/bin/install-bridge.mjs" --restore ;;
488
+ 4) node "$cli_dir/bin/install-bridge.mjs" --restore --apply ;;
489
+ 0) return ;;
490
+ *) warn "Unknown" ;;
491
+ esac
492
+ pause
493
+ }
494
+
495
+ # ------------------------------------------------------------
496
+ # Interactive wrapper for `bootstrap` — one-shot full migration
497
+ # ------------------------------------------------------------
498
+ menu_bootstrap() {
499
+ header
500
+ echo -e "${BOLD}${GREEN}▶ Bootstrap — full Prisma → @mostajs/orm migration${RESET}"
501
+ echo
502
+ echo "This will, in ${BOLD}this project${RESET} :"
503
+ echo " 1. Rewrite every ${CYAN}new PrismaClient()${RESET} site to use ${CYAN}createPrismaLikeDb()${RESET}"
504
+ echo " (originals backed up as ${DIM}*.prisma.bak${RESET})"
505
+ echo " 2. Install ${CYAN}@mostajs/orm${RESET} + ${CYAN}@mostajs/orm-bridge${RESET} + ${CYAN}server-only${RESET}"
506
+ echo " 3. Convert ${CYAN}prisma/schema.prisma${RESET} → ${DIM}.mostajs/generated/entities.json${RESET}"
507
+ echo " 4. Write ${DIM}.mostajs/config.env${RESET} (default : sqlite ./data.sqlite) and init DDL"
508
+ echo
509
+ warn "Existing code changes will be backed up but NOT committed — review the diff before pushing."
510
+ echo
511
+ local go; go=$(ask "Proceed? (y/N)" "N")
512
+ [[ "$go" =~ ^[yY]$ ]] || { info "Cancelled"; return; }
513
+ run_subcommand bootstrap
514
+ pause
515
+ }
516
+
464
517
  # ============================================================
465
518
  # ACTION 1 : CONVERT
466
519
  # ============================================================
@@ -2316,6 +2369,14 @@ EOF
2316
2369
 
2317
2370
  run_subcommand() {
2318
2371
  case "$1" in
2372
+ diagnose|diag|d)
2373
+ # mostajs diagnose [email] [password]
2374
+ # Walks through: config vs project datasource mismatch, DB connection,
2375
+ # user lookup, isActive check, bcrypt verification.
2376
+ local email="${2:-}"
2377
+ local password="${3:-}"
2378
+ action_diagnose_login "$email" "$password"
2379
+ ;;
2319
2380
  hash|h)
2320
2381
  # mostajs hash <plaintext> [cost]
2321
2382
  local pw="${2:-}"
@@ -2387,6 +2448,117 @@ run_subcommand() {
2387
2448
  health|h)
2388
2449
  action_healthcheck
2389
2450
  ;;
2451
+ install-bridge|ib)
2452
+ # mostajs install-bridge [--apply] [--file X] [--project P] [--restore]
2453
+ # Codemod : scans the project for `new PrismaClient(...)` sites and rewrites
2454
+ # them in place to use createPrismaLikeDb() from @mostajs/orm-bridge.
2455
+ # Dry-run by default ; pass --apply to write the changes.
2456
+ local cli_dir
2457
+ cli_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
2458
+ shift
2459
+ node "$cli_dir/bin/install-bridge.mjs" "$@"
2460
+ ;;
2461
+ bootstrap|b)
2462
+ # mostajs bootstrap : the full zero-touch migration for a Prisma project.
2463
+ # 1. Rewrite every `new PrismaClient(...)` site (install-bridge --apply)
2464
+ # 2. npm install @mostajs/orm @mostajs/orm-bridge @mostajs/orm-adapter server-only
2465
+ # 3. Convert prisma/schema.prisma → entities.json
2466
+ # 4. Write .mostajs/config.env + init SQLite DDL
2467
+ #
2468
+ # Hard stop-on-error : no step proceeds if the previous one failed.
2469
+ local cli_dir
2470
+ cli_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
2471
+ detect_project
2472
+ [[ ${#DETECTED_TYPES[@]} -eq 0 ]] && { err "No schema found. Bootstrap needs a prisma/schema.prisma (or OpenAPI/JSONSchema)."; exit 1; }
2473
+
2474
+ local BS_OK_CODEMOD=0 BS_OK_DEPS=0 BS_OK_CONVERT=0 BS_OK_DDL=0
2475
+
2476
+ # ─── Step 1 ───
2477
+ echo -e "\n\e[1m▶ Step 1/4 : rewrite PrismaClient sites\e[0m"
2478
+ if node "$cli_dir/bin/install-bridge.mjs" --apply; then
2479
+ BS_OK_CODEMOD=1
2480
+ else
2481
+ err "Step 1 failed — codemod returned non-zero. Aborting."; exit 1
2482
+ fi
2483
+
2484
+ # ─── Step 2 ───
2485
+ echo -e "\n\e[1m▶ Step 2/4 : install runtime deps (this can take 1-2 min)\e[0m"
2486
+ info " installing : @mostajs/orm @mostajs/orm-bridge @mostajs/orm-adapter server-only"
2487
+ if ( cd "$PROJECT_ROOT" && $PKG_MANAGER install \
2488
+ @mostajs/orm @mostajs/orm-bridge @mostajs/orm-adapter server-only \
2489
+ --legacy-peer-deps ); then
2490
+ BS_OK_DEPS=1
2491
+ ok " deps installed"
2492
+ else
2493
+ err "Step 2 failed — \`$PKG_MANAGER install\` returned non-zero."
2494
+ err "Fix your package manager / registry access and re-run \`mostajs bootstrap\`."
2495
+ exit 1
2496
+ fi
2497
+
2498
+ # ─── Step 3 ───
2499
+ echo -e "\n\e[1m▶ Step 3/4 : convert schema + init DDL\e[0m"
2500
+ local type="${DETECTED_TYPES[0]}" input
2501
+ case "$type" in
2502
+ prisma) input="$PRISMA_SCHEMA" ;;
2503
+ openapi) input="$OPENAPI_FILE" ;;
2504
+ jsonschema) input="${JSON_SCHEMAS[0]}" ;;
2505
+ esac
2506
+
2507
+ if run_adapter_convert "$type" "$input" "$GENERATED_DIR/entities.ts" && \
2508
+ [[ -s "$GENERATED_DIR/entities.json" || -s "$GENERATED_DIR/entities.ts" ]]; then
2509
+ BS_OK_CONVERT=1
2510
+ ok " schema converted → $GENERATED_DIR/entities.json"
2511
+ else
2512
+ err "Step 3.1 failed — schema conversion did not produce entities.json."
2513
+ err "Re-run manually : $CLI_NAME convert (or menu 1)"
2514
+ exit 1
2515
+ fi
2516
+
2517
+ mkdir -p "$CONFIG_DIR"
2518
+ if [[ ! -f "$CONFIG_DIR/config.env" ]]; then
2519
+ cat > "$CONFIG_DIR/config.env" <<CFG
2520
+ DB_DIALECT=sqlite
2521
+ SGBD_URI=./data.sqlite
2522
+ DB_SCHEMA_STRATEGY=update
2523
+ CFG
2524
+ ok " wrote $CONFIG_DIR/config.env (defaults: sqlite ./data.sqlite)"
2525
+ # Reload config so action_init_dialects picks up the new values
2526
+ load_env
2527
+ fi
2528
+
2529
+ if action_init_dialects; then
2530
+ BS_OK_DDL=1
2531
+ ok " DDL applied"
2532
+ else
2533
+ err "Step 3.2 failed — DDL init returned non-zero."
2534
+ err "Re-run manually : $CLI_NAME (menu 3)"
2535
+ exit 1
2536
+ fi
2537
+
2538
+ # ─── Step 4 ───
2539
+ echo -e "\n\e[1m▶ Step 4/4 : done\e[0m"
2540
+ if (( BS_OK_CODEMOD && BS_OK_DEPS && BS_OK_CONVERT && BS_OK_DDL )); then
2541
+ cat <<DONE
2542
+
2543
+ ✓ Bridge installed in-place. Original files backed up as *.prisma.bak
2544
+ ✓ Schema converted : $GENERATED_DIR/entities.json
2545
+ ✓ DDL applied (DB_DIALECT=\$(grep ^DB_DIALECT $CONFIG_DIR/config.env | cut -d= -f2))
2546
+
2547
+ Next :
2548
+ - Add seeds to $CONFIG_DIR/seeds/*.json (one file per entity)
2549
+ - $CLI_NAME # menu S → h (hash) → 4 (apply)
2550
+ - npm run dev
2551
+ - Open http://localhost:3000/login
2552
+
2553
+ To undo the codemod :
2554
+ $CLI_NAME install-bridge --restore --apply
2555
+
2556
+ DONE
2557
+ else
2558
+ err "Bootstrap finished with partial success — see messages above."
2559
+ exit 1
2560
+ fi
2561
+ ;;
2390
2562
  version|-v|--version)
2391
2563
  echo "$CLI_NAME $VERSION"
2392
2564
  ;;
@@ -2394,14 +2566,21 @@ run_subcommand() {
2394
2566
  cat <<EOF
2395
2567
  Usage :
2396
2568
  $CLI_NAME Interactive menu
2569
+ $CLI_NAME bootstrap One-shot migration : codemod + deps + convert + DDL
2570
+ $CLI_NAME install-bridge Codemod only (dry-run ; add --apply to write)
2571
+ $CLI_NAME install-bridge --apply Rewrite PrismaClient sites to use @mostajs/orm-bridge
2572
+ $CLI_NAME install-bridge --restore --apply Undo a prior install-bridge
2397
2573
  $CLI_NAME convert Run conversion (auto-detect schema type)
2398
2574
  $CLI_NAME detect Print detected schemas
2399
2575
  $CLI_NAME health Run health checks
2400
2576
  $CLI_NAME hash <password> [cost] Hash a password with bcrypt (cost default 10)
2401
2577
  $CLI_NAME verify <password> <hash> Check if a plain password matches a bcrypt hash
2578
+ $CLI_NAME diagnose [email] [pw] Walk through login diagnostics
2402
2579
  $CLI_NAME version Print version
2403
2580
 
2404
2581
  Examples:
2582
+ $CLI_NAME bootstrap → zero-touch migrate a Prisma project to @mostajs/orm
2583
+ $CLI_NAME install-bridge → preview rewrites without touching files
2405
2584
  $CLI_NAME hash 'Admin@123456' → \$2b\$10\$N9qo8uLOickgx2ZMRZoMyeIjZA...
2406
2585
  $CLI_NAME verify 'Admin@123456' '\$2b\$10\$N9qo...'
2407
2586
  EOF
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mostajs/orm-cli",
3
- "version": "0.3.2",
4
- "description": "Universal CLI to integrate @mostajs/orm into any project — auto-detects Prisma, OpenAPI, JSON Schema. Interactive menu + subcommands. 13 databases.",
3
+ "version": "0.4.1",
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",
7
7
  "type": "module",