drizzle-auto 1.1.3 → 1.1.4

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.
Files changed (2) hide show
  1. package/index.js +147 -121
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,155 +1,181 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const fs = require("fs");
4
- const path = require("path");
5
3
  const chokidar = require("chokidar");
6
4
  const { spawn } = require("child_process");
5
+ const path = require("path");
6
+ const fs = require("fs");
7
7
 
8
- /* =========================
9
- 🎨 COLORS (PRO ONLY)
10
- ========================= */
11
- const C = {
12
- reset: "\x1b[0m",
13
- bold: "\x1b[1m",
14
- cyan: "\x1b[36m",
15
- green: "\x1b[32m",
16
- yellow: "\x1b[33m",
17
- red: "\x1b[31m",
18
- magenta: "\x1b[35m",
19
- dim: "\x1b[2m",
20
- };
21
-
22
- /* =========================
23
- 🧭 ROOT
24
- ========================= */
25
- const ROOT = process.cwd();
26
- const PKG = path.join(ROOT, "package.json");
27
-
28
- /* =========================
29
- ADD tea SCRIPT
30
- ========================= */
31
- function injectTea() {
32
- if (!fs.existsSync(PKG)) return;
33
- const pkg = JSON.parse(fs.readFileSync(PKG, "utf8"));
34
- pkg.scripts ||= {};
35
-
36
- if (!pkg.scripts.tea) {
37
- pkg.scripts.tea = "drizzle-auto";
38
- fs.writeFileSync(PKG, JSON.stringify(pkg, null, 2));
39
- console.log(`${C.green}☕ Added:${C.reset} npm run tea`);
8
+ /* =======================
9
+ 🎨 NeonPulse UI Core
10
+ ======================= */
11
+ const PALETTE = ["\x1b[31m", "\x1b[32m", "\x1b[33m", "\x1b[34m", "\x1b[35m", "\x1b[36m"];
12
+ const RESET = "\x1b[0m";
13
+ const BOLD = "\x1b[1m";
14
+ const DIM = "\x1b[90m";
15
+
16
+ let colorIndex = 0;
17
+ const nextColor = () => PALETTE[colorIndex++ % PALETTE.length];
18
+ const rainbow = (text) => text.split("").map((c) => `${nextColor()}${c}`).join("") + RESET;
19
+
20
+ /* =======================
21
+ ⏳ Dynamic Spinner
22
+ ======================= */
23
+ const spinnerFrames = ["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];
24
+ let spinIndex = 0;
25
+ let spinnerInterval;
26
+
27
+ function startSpinner(text) {
28
+ stopSpinner();
29
+ spinnerInterval = setInterval(() => {
30
+ process.stdout.write(`\r${nextColor()}${spinnerFrames[spinIndex++ % spinnerFrames.length]} ${text}${RESET}`);
31
+ }, 80);
32
+ }
33
+
34
+ function stopSpinner() {
35
+ if (spinnerInterval) {
36
+ clearInterval(spinnerInterval);
37
+ spinnerInterval = null;
38
+ process.stdout.write("\r\x1b[K");
40
39
  }
41
40
  }
42
41
 
43
- /* =========================
44
- 🔍 FIND drizzle.config.*
45
- ========================= */
46
- function findConfig() {
47
- const exts = ["js", "mjs", "cjs", "ts", "mts"];
48
- let found = null;
49
-
50
- (function walk(dir) {
51
- if (found) return;
52
- for (const f of fs.readdirSync(dir, { withFileTypes: true })) {
53
- if (f.name === "node_modules" || f.name.startsWith(".")) continue;
54
- const p = path.join(dir, f.name);
55
- if (f.isDirectory()) walk(p);
56
- else {
57
- for (const e of exts) {
58
- if (f.name === `drizzle.config.${e}`) {
59
- found = p;
60
- return;
61
- }
62
- }
63
- }
42
+ /* =======================
43
+ 🧠 5-Step Logic Engine
44
+ ======================= */
45
+ let isRunning = false;
46
+ let hasActiveError = false;
47
+
48
+ // [STEP 2]: Justify All Infrastructure Files (Dynamic Format Support)
49
+ function justifyFiles() {
50
+ const root = process.cwd();
51
+
52
+ // চেক ১: কনফিগ ফাইল (js, mjs, ts, mts)
53
+ const config = ["ts", "js", "mjs", "mts"]
54
+ .map(ext => `drizzle.config.${ext}`)
55
+ .find(f => fs.existsSync(path.join(root, f)));
56
+
57
+ if (!config) return { ok: false, msg: "drizzle.config.(ts/js/mjs/mts) not found in project." };
58
+
59
+ // চেক ২: স্কিমা ফাইল জাস্টিফিকেশন (কনফিগ থেকে ডাইনামিকালি পাথ রিড করা)
60
+ try {
61
+ const content = fs.readFileSync(path.join(root, config), "utf8");
62
+ const schemaMatch = content.match(/schema:\s*["'](.+?)["']/);
63
+ if (schemaMatch && schemaMatch[1]) {
64
+ const schemaPath = path.join(root, schemaMatch[1]);
65
+ if (!fs.existsSync(schemaPath)) return { ok: false, msg: `Schema file missing at: ${schemaMatch[1]}` };
64
66
  }
65
- })(ROOT);
67
+ } catch (e) {
68
+ return { ok: false, msg: "Failed to read or parse config file." };
69
+ }
66
70
 
67
- return found;
71
+ return { ok: true };
68
72
  }
69
73
 
70
- /* =========================
71
- ⚙️ SAFE RUNNER (ERROR AWARE)
72
- ========================= */
73
- function run(cmd, args) {
74
+ // [STEP 3, 4, 5]: Command Executor with Strict Error Halt
75
+ function executeCommand(args, stepName) {
74
76
  return new Promise((resolve) => {
75
- let stderr = "";
77
+ let hasError = false;
78
+ startSpinner(`[${stepName}] In Progress...`);
79
+
80
+ const child = spawn("npx", args, { shell: true });
76
81
 
77
- const p = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
82
+ child.stdout.on("data", (data) => {
83
+ const out = data.toString();
84
+ // Spam filter for cloud/server-side DB pulling logs
85
+ if (!out.includes('Pulling schema')) {
86
+ stopSpinner();
87
+ process.stdout.write(`${DIM}${out}${RESET}`);
88
+ }
89
+ if (/error|failed|ENOTFOUND|ECONNREFUSED/i.test(out)) hasError = true;
90
+ });
78
91
 
79
- p.stdout.on("data", d => process.stdout.write(d));
80
- p.stderr.on("data", d => {
81
- stderr += d.toString();
82
- process.stderr.write(d);
92
+ child.stderr.on("data", (data) => {
93
+ const err = data.toString();
94
+ stopSpinner();
95
+ process.stderr.write(`\x1b[31m${err}${RESET}`);
96
+ hasError = true;
83
97
  });
84
98
 
85
- p.on("close", (code) => {
86
- resolve({ ok: code === 0, stderr });
99
+ child.on("close", (code) => {
100
+ stopSpinner();
101
+ resolve(code === 0 && !hasError);
87
102
  });
88
103
  });
89
104
  }
90
105
 
91
- /* =========================
92
- 🔁 PIPELINE (NO LIES)
93
- ========================= */
94
- let busy = false;
95
-
96
- async function pipeline(trigger) {
97
- if (busy) return;
98
- busy = true;
99
-
100
- console.log(`\n${C.cyan}⚡ Trigger →${C.reset} ${trigger}`);
101
-
102
- const config = findConfig();
103
- if (!config) {
104
- console.log(`${C.yellow}⚠ No drizzle.config found${C.reset}`);
105
- busy = false;
106
+ /* =======================
107
+ 🔄 The Sequential Workflow
108
+ ======================= */
109
+ async function startWorkflow(trigger) {
110
+ if (isRunning) return;
111
+ isRunning = true;
112
+
113
+ if (!hasActiveError) console.clear();
114
+ console.log(BOLD + rainbow("🚀 DRIZZLE-AUTO // UNIVERSAL SERVER-SIDE ENGINE"));
115
+ console.log(`${nextColor()}⚡ Trigger ${trigger}${RESET}\n`);
116
+
117
+ // STEP 2: Justify Files (Infrastructure Check)
118
+ const audit = justifyFiles();
119
+ if (!audit.ok) {
120
+ console.log(`\n\x1b[31m🛑 STEP 2 FAILED: ${audit.msg}${RESET}`);
121
+ hasActiveError = true;
122
+ isRunning = false;
106
123
  return;
107
124
  }
108
125
 
109
- console.log(`${C.magenta}▶ drizzle-kit generate${C.reset}`);
110
- const gen = await run("npx", ["drizzle-kit", "generate"]);
111
- if (!gen.ok) {
112
- console.log(`${C.red}🛑 Generate failed watcher alive${C.reset}`);
113
- busy = false;
126
+ // STEP 3: Confirm no bug in code (Integrity Check)
127
+ const step3 = await executeCommand(["drizzle-kit", "check"], "Step 3: Bug Check");
128
+ if (!step3) {
129
+ console.log(`\n\x1b[31m🛑 STEP 3 FAILED: Bugs or Drifts detected. Halting Pipeline.${RESET}`);
130
+ hasActiveError = true;
131
+ isRunning = false;
114
132
  return;
115
133
  }
116
134
 
117
- console.log(`${C.magenta}▶ drizzle-kit push${C.reset}`);
118
- const push = await run("npx", ["drizzle-kit", "push"]);
119
-
120
- if (!push.ok) {
121
- console.log(`\n${C.red}${C.bold}🚨 PUSH FAILED${C.reset}`);
122
-
123
- if (
124
- push.stderr.includes("ENOTFOUND") ||
125
- push.stderr.includes("websocket")
126
- ) {
127
- console.log(
128
- `${C.yellow}⚠ Neon / network issue detected${C.reset}\n` +
129
- `${C.dim}• Check internet\n` +
130
- `• Check DATABASE_URL\n` +
131
- `• Neon endpoint may be sleeping${C.reset}`
132
- );
133
- }
135
+ // STEP 4: Run Drizzle Generate
136
+ const step4 = await executeCommand(["drizzle-kit", "generate"], "Step 4: Generate");
137
+ if (!step4) {
138
+ console.log(`\n\x1b[31m🛑 STEP 4 FAILED: Migration generation failed.${RESET}`);
139
+ hasActiveError = true;
140
+ isRunning = false;
141
+ return;
142
+ }
134
143
 
135
- console.log(`${C.dim}Watcher still running. Server NOT stopped.${C.reset}`);
136
- busy = false;
144
+ // STEP 5: Push Changes
145
+ const step5 = await executeCommand(["drizzle-kit", "push"], "Step 5: Push");
146
+ if (!step5) {
147
+ console.log(`\n\x1b[31m🛑 STEP 5 FAILED: DB Push failed. Check connection.${RESET}`);
148
+ hasActiveError = true;
149
+ isRunning = false;
137
150
  return;
138
151
  }
139
152
 
140
- console.log(`${C.green}✨ Drizzle fully synced${C.reset}`);
141
- busy = false;
153
+ // ALL STEPS SUCCESS
154
+ hasActiveError = false;
155
+ console.log(`\n\x1b[32m${BOLD}✨ SUCCESS: 5/5 Steps Completed. All systems justified!${RESET}`);
156
+
157
+ setTimeout(() => {
158
+ isRunning = false;
159
+ console.log(`\n${DIM}🛰️ System justified. Watching for next change...${RESET}`);
160
+ }, 2000);
142
161
  }
143
162
 
144
- /* =========================
145
- 👀 WATCH EVERYTHING
146
- ========================= */
147
- injectTea();
148
- pipeline("Initial");
149
-
150
- chokidar.watch(ROOT, {
151
- ignored: [/node_modules/, /\.git/, /\.next/, /dist/],
163
+ /* =======================
164
+ 👀 Universal Watcher
165
+ ======================= */
166
+ chokidar.watch(".", {
167
+ ignored: [/node_modules/, /\.git/, /\.next/, /dist/, /drizzle/],
152
168
  ignoreInitial: true,
153
- }).on("all", (_, file) => {
154
- pipeline(path.relative(ROOT, file));
155
- });
169
+ usePolling: true,
170
+ interval: 300
171
+ }).on("all", (e, f) => startWorkflow(`${e.toUpperCase()} → ${path.basename(f)}`));
172
+
173
+ // Init Call
174
+ startWorkflow("Initial System Audit");
175
+
176
+ // Safety Net
177
+ process.on("uncaughtException", (err) => {
178
+ stopSpinner();
179
+ console.log(`\n\x1b[31m🛡️ Shield Error: ${err.message}${RESET}`);
180
+ isRunning = false;
181
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-auto",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "pavel ahmmed hridoy",