drizzle-auto 1.1.0 → 1.1.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.
Files changed (2) hide show
  1. package/index.js +101 -70
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -6,28 +6,37 @@ const chokidar = require("chokidar");
6
6
  const { spawn } = require("child_process");
7
7
 
8
8
  /* =========================
9
- 🎨 COLORS (PRO)
9
+ 🎨 COLORS (clean & pro)
10
10
  ========================= */
11
11
  const C = {
12
12
  reset: "\x1b[0m",
13
- blue: "\x1b[34m",
13
+ dim: "\x1b[2m",
14
+ bold: "\x1b[1m",
14
15
  cyan: "\x1b[36m",
15
16
  green: "\x1b[32m",
16
17
  yellow: "\x1b[33m",
17
18
  red: "\x1b[31m",
18
- dim: "\x1b[90m",
19
+ magenta: "\x1b[35m",
20
+ };
21
+
22
+ const log = {
23
+ info: (m) => console.log(`${C.cyan}ℹ ${m}${C.reset}`),
24
+ ok: (m) => console.log(`${C.green}✓ ${m}${C.reset}`),
25
+ warn: (m) => console.log(`${C.yellow}⚠ ${m}${C.reset}`),
26
+ err: (m) => console.log(`${C.red}✗ ${m}${C.reset}`),
27
+ trig: (m) => console.log(`${C.magenta}⚡ ${m}${C.reset}`),
19
28
  };
20
29
 
21
30
  /* =========================
22
- 🧭 ROOT + PKG
31
+ 🧭 PROJECT ROOT
23
32
  ========================= */
24
33
  const ROOT = process.cwd();
25
34
  const PKG = path.join(ROOT, "package.json");
26
35
 
27
36
  /* =========================
28
- SCRIPT INJECTOR
37
+ 🧩 SCRIPT INJECTOR
29
38
  ========================= */
30
- function injectTea() {
39
+ function injectScript() {
31
40
  if (!fs.existsSync(PKG)) return;
32
41
 
33
42
  const pkg = JSON.parse(fs.readFileSync(PKG, "utf8"));
@@ -36,115 +45,137 @@ function injectTea() {
36
45
  if (!pkg.scripts.tea) {
37
46
  pkg.scripts.tea = "drizzle-auto";
38
47
  fs.writeFileSync(PKG, JSON.stringify(pkg, null, 2));
39
- console.log(`${C.cyan}☕ Added script: npm run tea${C.reset}`);
48
+ log.ok("Added script npm run tea");
40
49
  }
41
50
  }
42
51
 
43
52
  /* =========================
44
- 🔍 RECURSIVE SEARCH
53
+ 🔍 FIND DRIZZLE CONFIG
54
+ (js | mjs | ts | mts)
45
55
  ========================= */
46
- function walk(dir, results = []) {
47
- for (const file of fs.readdirSync(dir)) {
48
- const p = path.join(dir, file);
49
- if (p.includes("node_modules") || p.includes(".git")) continue;
50
-
51
- const stat = fs.statSync(p);
52
- if (stat.isDirectory()) walk(p, results);
53
- else results.push(p);
54
- }
55
- return results;
56
- }
57
-
58
56
  function findDrizzleConfig() {
59
- const files = walk(ROOT);
60
- const config = files.find(f =>
61
- /drizzle\.config\.(js|mjs|ts|mts)$/.test(f)
62
- );
63
-
64
- if (!config) {
65
- console.log(`${C.yellow}⚠️ drizzle.config not found (anywhere)${C.reset}`);
66
- return null;
67
- }
68
-
69
- let schemaPath = null;
70
- try {
71
- const content = fs.readFileSync(config, "utf8");
72
- const match = content.match(/schema:\s*["'](.+?)["']/);
73
- if (match) {
74
- schemaPath = path.resolve(path.dirname(config), match[1]);
75
- }
76
- } catch {}
77
-
78
- if (schemaPath && !fs.existsSync(schemaPath)) {
79
- console.log(`${C.red}❌ Schema missing: ${schemaPath}${C.reset}`);
80
- return null;
57
+ const exts = ["js", "mjs", "ts", "mts"];
58
+ for (const e of exts) {
59
+ const p = path.join(ROOT, `drizzle.config.${e}`);
60
+ if (fs.existsSync(p)) return p;
81
61
  }
62
+ return null;
63
+ }
82
64
 
83
- console.log(`${C.green}✔ Drizzle config found${C.reset}`);
84
- return true;
65
+ /* =========================
66
+ 🔎 FILE FILTER (ALL TYPES)
67
+ ========================= */
68
+ const WATCH_EXTS = [
69
+ ".js", ".mjs", ".cjs",
70
+ ".ts", ".mts",
71
+ ".jsx", ".tsx",
72
+ ".sql"
73
+ ];
74
+
75
+ function isValidFile(file) {
76
+ return WATCH_EXTS.includes(path.extname(file));
85
77
  }
86
78
 
87
79
  /* =========================
88
- ⚙️ COMMAND RUNNER
80
+ ⚙️ SAFE SPAWN (NO SHELL)
89
81
  ========================= */
90
- function run(cmd) {
91
- return new Promise(resolve => {
92
- let failed = false;
93
- const p = spawn("npx", cmd, { shell: true });
94
-
95
- p.stdout.on("data", d =>
96
- process.stdout.write(C.dim + d.toString() + C.reset)
97
- );
98
- p.stderr.on("data", d => {
99
- failed = true;
100
- process.stderr.write(C.red + d.toString() + C.reset);
82
+ function exec(cmd, args = []) {
83
+ return new Promise((resolve) => {
84
+ const p = spawn(cmd, args, { stdio: "inherit" });
85
+
86
+ p.on("error", (e) => {
87
+ log.err(`Process error: ${e.message}`);
88
+ resolve(false);
101
89
  });
102
90
 
103
- p.on("close", code => resolve(code === 0 && !failed));
91
+ p.on("close", (code) => {
92
+ resolve(code === 0);
93
+ });
104
94
  });
105
95
  }
106
96
 
107
97
  /* =========================
108
- 🔁 PIPELINE (SAFE)
98
+ 🛡️ CRASH PROTECTION
99
+ ========================= */
100
+ process.on("uncaughtException", (e) => {
101
+ log.err(`Crash prevented: ${e.message}`);
102
+ });
103
+ process.on("unhandledRejection", (e) => {
104
+ log.err(`Promise rejected: ${e}`);
105
+ });
106
+
107
+ /* =========================
108
+ 🔁 PIPELINE (DEV SAFE)
109
109
  ========================= */
110
110
  let running = false;
111
+ let lastPush = 0;
112
+
113
+ const DEV_MODE = process.argv.includes("--dev");
114
+ const PUSH_COOLDOWN = DEV_MODE ? 120_000 : 30_000; // safer in dev
111
115
 
112
116
  async function pipeline(trigger) {
113
117
  if (running) return;
114
118
  running = true;
115
119
 
116
- console.log(`${C.blue}\n⚡ Trigger → ${trigger}${C.reset}`);
120
+ log.trig(`Trigger → ${trigger}`);
117
121
 
118
- if (!findDrizzleConfig()) {
122
+ const config = findDrizzleConfig();
123
+ if (!config) {
124
+ log.warn("No drizzle.config found");
119
125
  running = false;
120
126
  return;
121
127
  }
122
128
 
123
- if (!(await run(["drizzle-kit", "generate"]))) {
124
- console.log(`${C.red}🛑 generate failed (watcher alive)${C.reset}`);
129
+ log.info("Running drizzle generate");
130
+ const gen = await exec("npx", ["drizzle-kit", "generate"]);
131
+ if (!gen) {
132
+ log.err("Generate failed — watching continues");
125
133
  running = false;
126
134
  return;
127
135
  }
128
136
 
129
- if (!(await run(["drizzle-kit", "push"]))) {
130
- console.log(`${C.red}🛑 push failed (watcher alive)${C.reset}`);
137
+ const now = Date.now();
138
+ if (now - lastPush < PUSH_COOLDOWN) {
139
+ log.warn("Push skipped (cooldown)");
131
140
  running = false;
132
141
  return;
133
142
  }
134
143
 
135
- console.log(`${C.green}✨ Drizzle synced${C.reset}`);
144
+ log.info("Running drizzle push…");
145
+ lastPush = now;
146
+
147
+ const push = await exec("npx", ["drizzle-kit", "push"]);
148
+ if (!push) {
149
+ log.err("Push failed — DB untouched, server alive");
150
+ running = false;
151
+ return;
152
+ }
153
+
154
+ log.ok("Drizzle fully synced");
136
155
  running = false;
137
156
  }
138
157
 
139
158
  /* =========================
140
- 👀 WATCHER
159
+ 👀 WATCHER (ALL FILES)
141
160
  ========================= */
142
- injectTea();
143
- pipeline("initial");
161
+ injectScript();
162
+ pipeline("Initial");
163
+
164
+ log.info(`Watching files (${DEV_MODE ? "DEV MODE" : "SAFE MODE"})…`);
144
165
 
145
166
  chokidar.watch(ROOT, {
146
- ignored: [/node_modules/, /\.git/, /\.next/, /dist/],
167
+ ignored: [
168
+ /node_modules/,
169
+ /\.git/,
170
+ /\.next/,
171
+ /dist/,
172
+ /build/
173
+ ],
147
174
  ignoreInitial: true,
148
175
  usePolling: true,
149
176
  interval: 300,
150
- }).on("all", (_, file) => pipeline(path.basename(file)));
177
+ }).on("all", (_, file) => {
178
+ if (isValidFile(file)) {
179
+ pipeline(path.relative(ROOT, file));
180
+ }
181
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-auto",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "pavel ahmmed hridoy",