drizzle-auto 1.1.24 → 1.1.26

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 +112 -108
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,187 +1,191 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * 🌟 Drizzle-Auto v2 - Fail-Fast Version
5
- * 🔹 Stops immediately on any error
6
- * 🔹 Strict config: drizzle.config.js / ts / mjs / cjs
7
- * 🔹 Watcher disabled on --postinstall
8
- * 🔹 Full error catching
4
+ * 🍵 Drizzle-Auto v2.3 - Flexible Config + Fail-Fast
5
+ * 🔹 Detects any drizzle.config.{js,ts,mjs,cjs,mts} automatically
6
+ * 🔹 Stops immediately if config or schema missing
7
+ * 🔹 Beginner-friendly logs
9
8
  */
10
9
 
11
10
  const { spawn } = require("child_process");
12
11
  const path = require("path");
13
12
  const fs = require("fs");
14
13
 
15
- // Optional TS support
14
+ // TS support
16
15
  try { require("ts-node").register({ transpileOnly: true }); } catch(e){}
17
16
 
18
- // ---------------------- COLORS ----------------------
17
+ // ---------------- COLORS ----------------
19
18
  const T = {
20
19
  reset: "\x1b[0m",
21
20
  bold: "\x1b[1m",
22
21
  cyan: "\x1b[38;5;51m",
23
- pink: "\x1b[38;5;201m",
24
22
  lime: "\x1b[38;5;118m",
25
23
  yellow: "\x1b[38;5;226m",
26
24
  red: "\x1b[38;5;196m",
27
25
  gray: "\x1b[38;5;244m",
28
26
  };
29
27
 
30
- // ---------------------- SPINNER ----------------------
28
+ let spinInterval;
31
29
  const frames = ["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];
32
- let spinIdx = 0, spinInterval;
30
+ let spinIdx = 0;
33
31
 
34
32
  function startLoading(msg){
35
33
  stopLoading();
36
34
  spinInterval = setInterval(()=>{
37
35
  process.stdout.write(`\r${T.cyan}${frames[spinIdx++ % frames.length]}${T.reset} ${T.bold}${msg}${T.reset} `);
38
- }, 80);
36
+ },80);
39
37
  }
40
38
 
41
39
  function stopLoading(){
42
40
  if(spinInterval){
43
41
  clearInterval(spinInterval);
44
- spinInterval = null;
42
+ spinInterval=null;
45
43
  process.stdout.write("\r\x1b[K");
46
44
  }
47
45
  }
48
46
 
49
- // ---------------------- INJECT "tea" SCRIPT ----------------------
50
- const PKG = path.join(process.cwd(), "package.json");
51
- function injectScript() {
52
- if (!fs.existsSync(PKG)) return;
53
- const pkg = JSON.parse(fs.readFileSync(PKG, "utf8"));
54
- pkg.scripts ||= {};
55
- if (!pkg.scripts.tea) {
56
- pkg.scripts.tea = "drizzle-auto";
57
- console.log(`${T.lime}🍵 Script added → npm/yarn/pnpm run tea${T.reset}`);
58
- fs.writeFileSync(PKG, JSON.stringify(pkg, null, 2));
59
- }
47
+ // ---------------- ADD "tea" SCRIPT ----------------
48
+ const PKG = path.join(process.cwd(),"package.json");
49
+ function addTeaScript(){
50
+ if(!fs.existsSync(PKG)) return;
51
+ try{
52
+ const pkg = JSON.parse(fs.readFileSync(PKG,"utf8"));
53
+ pkg.scripts ||= {};
54
+ if(!pkg.scripts.tea){
55
+ pkg.scripts.tea = "drizzle-auto";
56
+ fs.writeFileSync(PKG, JSON.stringify(pkg,null,2));
57
+ console.log(`${T.lime}🍵 Added script → npm run tea${T.reset}`);
58
+ }
59
+ } catch(e){}
60
60
  }
61
- injectScript();
62
-
63
- // ---------------------- STRICT CONFIG DETECTION ----------------------
64
- function findDrizzleConfig(root){
65
- const allowed = [
66
- "drizzle.config.js",
67
- "drizzle.config.ts",
68
- "drizzle.config.mjs",
69
- "drizzle.config.cjs"
70
- ];
71
- const files = [];
72
- function walk(dir){
73
- fs.readdirSync(dir,{withFileTypes:true}).forEach(file=>{
74
- const full = path.join(dir,file.name);
75
- if(file.isDirectory() && !/node_modules|\.git|\.next|dist/.test(file.name)) walk(full);
76
- else if(file.isFile() && allowed.includes(file.name)) files.push(full);
77
- });
61
+
62
+ // ---------------- FIND ANY DRIZZLE CONFIG ----------------
63
+ function findConfig(){
64
+ const allowedExts = ["js","ts","mjs","cjs","mts"];
65
+ const rootFiles = fs.readdirSync(process.cwd());
66
+ for(const file of rootFiles){
67
+ const match = file.match(/^drizzle\.config\.(.+)$/i);
68
+ if(match && allowedExts.includes(match[1])) return path.join(process.cwd(),file);
78
69
  }
79
- walk(root);
80
- return files;
70
+ return null;
81
71
  }
82
72
 
83
- // ---------------------- VALIDATE SCHEMA ----------------------
84
- function validateSchema(){
85
- const configs = findDrizzleConfig(process.cwd());
86
- if(configs.length === 0)
87
- return { ok:false, msg:"Missing strict drizzle.config.js / ts / mjs / cjs" };
88
-
89
- for(const cfg of configs){
90
- try {
91
- let schemaPath;
92
- const mod = require(cfg);
93
- schemaPath = mod.default?.schema || mod.schema;
94
-
95
- if(!schemaPath) continue;
96
-
97
- const schemaFull = path.resolve(path.dirname(cfg), schemaPath);
98
- if(!fs.existsSync(schemaFull))
99
- return { ok:false, msg:`Schema not found: ${schemaPath} in ${cfg}` };
100
-
101
- } catch(e){
102
- return { ok:false, msg:`Config parse error in ${cfg}: ${e.message}` };
73
+ // ---------------- CHECK SCHEMA ----------------
74
+ function checkSchema(configPath){
75
+ try{
76
+ const cfg = require(configPath);
77
+ const schemaPath = cfg.default?.schema || cfg.schema;
78
+ if(!schemaPath){
79
+ console.log(`${T.yellow}⚠ Warning: schema not defined in ${path.basename(configPath)}${T.reset}`);
80
+ return true; // optional
81
+ }
82
+ const fullSchema = path.resolve(path.dirname(configPath), schemaPath);
83
+ if(!fs.existsSync(fullSchema)){
84
+ console.log(`${T.red}❌ ERROR: Schema file missing → ${fullSchema}${T.reset}`);
85
+ process.exit(1);
103
86
  }
87
+ return true;
88
+ } catch(e){
89
+ console.log(`${T.red}❌ ERROR: Cannot read config → ${e.message}${T.reset}`);
90
+ process.exit(1);
104
91
  }
105
-
106
- return { ok:true, config:configs };
107
92
  }
108
93
 
109
- // ---------------------- RUN SHELL COMMAND ----------------------
110
- function runCommand(cmd, label){
111
- return new Promise((resolve, reject) => {
94
+ // ---------------- RUN SHELL COMMAND ----------------
95
+ function runCommand(cmd,label){
96
+ return new Promise((resolve,reject)=>{
112
97
  startLoading(label);
113
- const child = spawn(cmd, { shell: true, stdio: "inherit" });
114
- child.on("close", code => {
98
+ const child = spawn(cmd,{shell:true,stdio:["inherit","inherit","pipe"]});
99
+ let stderrData = "";
100
+ child.stderr.on("data", d=>{
101
+ stderrData += d.toString();
102
+ process.stderr.write(d);
103
+ });
104
+ child.on("close", code=>{
115
105
  stopLoading();
116
- if(code !== 0) reject(new Error(`${label} failed with exit code ${code}`));
106
+ const hasError = code!==0 || /ErrorEvent|ENOTFOUND|failed to connect/i.test(stderrData);
107
+ if(hasError) reject(new Error(`${label} failed!`));
117
108
  else resolve();
118
109
  });
119
- child.on("error", err => {
110
+ child.on("error", err=>{
120
111
  stopLoading();
121
- reject(new Error(`${label} failed: ${err.message}`));
112
+ reject(err);
122
113
  });
123
114
  });
124
115
  }
125
116
 
126
- // ---------------------- ENGINE ----------------------
127
- let running = false;
117
+ // ---------------- ENGINE ----------------
118
+ let isRunning=false;
128
119
  async function triggerEngine(){
129
- if(running) return;
130
- running = true;
131
-
132
- const audit = validateSchema();
133
- if(!audit.ok){
134
- console.log(`${T.red}${T.bold}👾 CRITICAL FAILURE:${T.reset} ${audit.msg}`);
135
- running = false;
136
- process.exit(1); // <- stop immediately
120
+ if(isRunning) return;
121
+ isRunning=true;
122
+
123
+ const configPath = findConfig();
124
+ if(!configPath){
125
+ console.log(`${T.red} ERROR: No drizzle config found!${T.reset}`);
126
+ console.log(`${T.yellow}Expected one of: drizzle.config.js/ts/mjs/cjs/mts${T.reset}`);
127
+ process.exit(1);
137
128
  }
138
129
 
130
+ checkSchema(configPath);
131
+
139
132
  const steps = [
140
- {name:"Integrity Check", cmd:"drizzle-kit check"},
141
- {name:"Generate Migration", cmd:"drizzle-kit generate"},
142
- {name:"Push Database", cmd:"drizzle-kit push"}
133
+ {name:"Integrity Check", cmd:"npx drizzle-kit check"},
134
+ {name:"Generate Migration", cmd:"npx drizzle-kit generate"},
135
+ {name:"Push Database", cmd:"npx drizzle-kit push"}
143
136
  ];
144
137
 
145
- try {
138
+ try{
146
139
  for(const step of steps){
147
- await runCommand(step.cmd, step.name);
140
+ await runCommand(step.cmd,step.name);
148
141
  }
149
- console.log(`${T.lime}${T.bold}🎉 All steps successful!${T.reset}`);
150
- } catch(err){
151
- console.log(`${T.red}🚨 ERROR: ${err.message}${T.reset}`);
152
- process.exit(1); // <- stop immediately on any error
142
+ console.log(`\n${T.lime}🎉 SUCCESS: All steps finished.${T.reset}\n`);
143
+ } catch(e){
144
+ console.log(`\n${T.red}🚨 CRITICAL STOP: ${e.message}${T.reset}`);
145
+ process.exit(1);
146
+ } finally{
147
+ isRunning=false;
153
148
  }
154
-
155
- running = false;
156
149
  }
157
150
 
158
- // ---------------------- WATCHER ----------------------
159
- const skipWatcher = process.argv.includes('--postinstall');
151
+ // ---------------- MAIN ----------------
152
+ addTeaScript();
160
153
 
161
- if(!skipWatcher){
162
- const configsExist = findDrizzleConfig(process.cwd()).length > 0;
163
- if(configsExist){
164
- triggerEngine();
154
+ const skipWatcher = process.argv.includes("--postinstall");
165
155
 
156
+ if(skipWatcher){
157
+ triggerEngine();
158
+ }else{
159
+ triggerEngine();
160
+
161
+ try{
166
162
  const chokidar = require("chokidar");
163
+ let timer;
167
164
  chokidar.watch(".",{
168
- ignored:[/node_modules/,/\.git/,/\.next|dist/],
165
+ ignored:[/node_modules/,/\.git/,/\.next/,/dist/,/out/],
169
166
  ignoreInitial:true,
170
167
  usePolling:true,
171
168
  interval:300
172
- }).on("all", (e,f) => triggerEngine());
173
- } else {
174
- console.log(`${T.yellow}⚠ No strict drizzle.config found. Watcher disabled.${T.reset}`);
169
+ }).on("all",(e,f)=>{
170
+ clearTimeout(timer);
171
+ timer=setTimeout(()=>{
172
+ console.log(`${T.gray}🔄 Change detected, re-running...${T.reset}`);
173
+ triggerEngine();
174
+ },500);
175
+ });
176
+ console.log(`${T.gray}👀 Watching for changes in config/schema...${T.reset}`);
177
+ } catch(e){
178
+ console.log(`${T.yellow}⚠ Chokidar not installed. Watch mode disabled.${T.reset}`);
175
179
  }
176
180
  }
177
181
 
178
- // ---------------------- GLOBAL ERROR HANDLING ----------------------
179
- process.on("uncaughtException", err=>{
180
- console.log(`${T.red}${T.bold}🛡️ UNCAUGHT ERROR:${T.reset} ${err.message}`);
181
- process.exit(1); // <- stop immediately
182
+ // ---------------- GLOBAL ERROR CATCH ----------------
183
+ process.on("uncaughtException",err=>{
184
+ console.log(`${T.red}🛡️ UNCAUGHT ERROR: ${err.message}${T.reset}`);
185
+ process.exit(1);
182
186
  });
183
187
 
184
- process.on("SIGINT", ()=>{
188
+ process.on("SIGINT",()=>{
185
189
  console.log(`${T.yellow}Shutting down Drizzle-Auto...${T.reset}`);
186
190
  process.exit(0);
187
191
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-auto",
3
- "version": "1.1.24",
3
+ "version": "1.1.26",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "pavel ahmmed hridoy",