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.
- package/index.js +112 -108
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,187 +1,191 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* 🔹
|
|
6
|
-
* 🔹
|
|
7
|
-
* 🔹
|
|
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
|
-
//
|
|
14
|
+
// TS support
|
|
16
15
|
try { require("ts-node").register({ transpileOnly: true }); } catch(e){}
|
|
17
16
|
|
|
18
|
-
//
|
|
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
|
-
|
|
28
|
+
let spinInterval;
|
|
31
29
|
const frames = ["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];
|
|
32
|
-
let spinIdx = 0
|
|
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
|
-
},
|
|
36
|
+
},80);
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
function stopLoading(){
|
|
42
40
|
if(spinInterval){
|
|
43
41
|
clearInterval(spinInterval);
|
|
44
|
-
spinInterval
|
|
42
|
+
spinInterval=null;
|
|
45
43
|
process.stdout.write("\r\x1b[K");
|
|
46
44
|
}
|
|
47
45
|
}
|
|
48
46
|
|
|
49
|
-
//
|
|
50
|
-
const PKG = path.join(process.cwd(),
|
|
51
|
-
function
|
|
52
|
-
if
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
pkg.scripts.tea
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
80
|
-
return files;
|
|
70
|
+
return null;
|
|
81
71
|
}
|
|
82
72
|
|
|
83
|
-
//
|
|
84
|
-
function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
//
|
|
110
|
-
function runCommand(cmd,
|
|
111
|
-
return new Promise((resolve,
|
|
94
|
+
// ---------------- RUN SHELL COMMAND ----------------
|
|
95
|
+
function runCommand(cmd,label){
|
|
96
|
+
return new Promise((resolve,reject)=>{
|
|
112
97
|
startLoading(label);
|
|
113
|
-
const child = spawn(cmd,
|
|
114
|
-
|
|
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
|
-
|
|
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(
|
|
112
|
+
reject(err);
|
|
122
113
|
});
|
|
123
114
|
});
|
|
124
115
|
}
|
|
125
116
|
|
|
126
|
-
//
|
|
127
|
-
let
|
|
117
|
+
// ---------------- ENGINE ----------------
|
|
118
|
+
let isRunning=false;
|
|
128
119
|
async function triggerEngine(){
|
|
129
|
-
if(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
if(!
|
|
134
|
-
console.log(`${T.red}
|
|
135
|
-
|
|
136
|
-
process.exit(1);
|
|
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,
|
|
140
|
+
await runCommand(step.cmd,step.name);
|
|
148
141
|
}
|
|
149
|
-
console.log(
|
|
150
|
-
} catch(
|
|
151
|
-
console.log(
|
|
152
|
-
process.exit(1);
|
|
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
|
-
//
|
|
159
|
-
|
|
151
|
+
// ---------------- MAIN ----------------
|
|
152
|
+
addTeaScript();
|
|
160
153
|
|
|
161
|
-
|
|
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
|
|
165
|
+
ignored:[/node_modules/,/\.git/,/\.next/,/dist/,/out/],
|
|
169
166
|
ignoreInitial:true,
|
|
170
167
|
usePolling:true,
|
|
171
168
|
interval:300
|
|
172
|
-
}).on("all",
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
//
|
|
179
|
-
process.on("uncaughtException",
|
|
180
|
-
console.log(`${T.red}
|
|
181
|
-
process.exit(1);
|
|
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
|
});
|