drizzle-auto 1.1.5 → 1.1.7
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 +169 -129
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -6,163 +6,203 @@ const path = require("path");
|
|
|
6
6
|
const fs = require("fs");
|
|
7
7
|
|
|
8
8
|
/* =============================================================
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
🎨 NEON-PULSE UI CORE (ChatGPT-Like Aesthetics)
|
|
10
|
+
============================================================= */
|
|
11
|
+
const T = {
|
|
12
|
+
reset: "\x1b[0m",
|
|
13
|
+
bold: "\x1b[1m",
|
|
14
|
+
italic: "\x1b[3m",
|
|
15
|
+
underline: "\x1b[4m",
|
|
16
|
+
cyan: "\x1b[38;5;51m",
|
|
17
|
+
pink: "\x1b[38;5;201m",
|
|
18
|
+
lime: "\x1b[38;5;118m",
|
|
19
|
+
yellow: "\x1b[38;5;226m",
|
|
20
|
+
red: "\x1b[38;5;196m",
|
|
21
|
+
gray: "\x1b[38;5;244m",
|
|
22
|
+
magenta: "\x1b[38;5;201m",
|
|
23
|
+
bg_dark: "\x1b[48;5;234m"
|
|
21
24
|
};
|
|
22
25
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
const rainbow = (text) => {
|
|
27
|
+
const colors = [196, 208, 226, 118, 51, 201];
|
|
28
|
+
return text.split('').map((char, i) => `\x1b[38;5;${colors[i % colors.length]}m${char}`).join('') + T.reset;
|
|
29
|
+
};
|
|
26
30
|
|
|
27
31
|
/* =============================================================
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
⏳ HIGH-FIDELITY SPINNER & LOADING
|
|
33
|
+
============================================================= */
|
|
34
|
+
const frames = ["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];
|
|
35
|
+
let spinIdx = 0;
|
|
36
|
+
let spinInterval;
|
|
37
|
+
|
|
38
|
+
function startLoading(msg) {
|
|
39
|
+
stopLoading();
|
|
40
|
+
spinInterval = setInterval(() => {
|
|
41
|
+
process.stdout.write(`\r${T.cyan}${frames[spinIdx++ % frames.length]}${T.reset} ${T.bold}${msg}${T.reset} `);
|
|
42
|
+
}, 80);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function stopLoading() {
|
|
46
|
+
if (spinInterval) {
|
|
47
|
+
clearInterval(spinInterval);
|
|
48
|
+
spinInterval = null;
|
|
49
|
+
process.stdout.write("\r\x1b[K"); // Clear line
|
|
50
|
+
}
|
|
41
51
|
}
|
|
42
52
|
|
|
43
53
|
/* =============================================================
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
🧩 AUTO SCRIPT INJECTOR
|
|
55
|
+
============================================================= */
|
|
56
|
+
const PKG = path.join(process.cwd(), "package.json");
|
|
57
|
+
function injectScript() {
|
|
58
|
+
if (!fs.existsSync(PKG)) return;
|
|
59
|
+
const pkg = JSON.parse(fs.readFileSync(PKG, "utf8"));
|
|
60
|
+
pkg.scripts ||= {};
|
|
61
|
+
if (!pkg.scripts.tea) {
|
|
62
|
+
pkg.scripts.tea = "drizzle-auto";
|
|
63
|
+
fs.writeFileSync(PKG, JSON.stringify(pkg, null, 2));
|
|
64
|
+
console.log(`${T.lime}☕ Script added → npm run tea${T.reset}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
injectScript();
|
|
68
|
+
|
|
69
|
+
/* =============================================================
|
|
70
|
+
🔍 ALL FILES DRIZZLE DETECTOR
|
|
71
|
+
============================================================= */
|
|
72
|
+
function findDrizzleConfig(root) {
|
|
73
|
+
const exts = ["js","mjs","ts","mts","cjs"];
|
|
74
|
+
const files = [];
|
|
75
|
+
|
|
76
|
+
function walk(dir) {
|
|
77
|
+
fs.readdirSync(dir, { withFileTypes: true }).forEach(file => {
|
|
78
|
+
const full = path.join(dir, file.name);
|
|
79
|
+
if (file.isDirectory() && !/node_modules|\.git|\.next|dist/.test(file.name)) {
|
|
80
|
+
walk(full);
|
|
81
|
+
} else if (file.isFile() && exts.some(ext => file.name === `drizzle.config.${ext}`)) {
|
|
82
|
+
files.push(full);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
walk(root);
|
|
88
|
+
return files;
|
|
60
89
|
}
|
|
61
90
|
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
91
|
+
function justifyStructure() {
|
|
92
|
+
const root = process.cwd();
|
|
93
|
+
const configs = findDrizzleConfig(root);
|
|
94
|
+
if (configs.length === 0) return { ok: false, msg: "Missing drizzle.config.*" };
|
|
65
95
|
|
|
96
|
+
for (const configPath of configs) {
|
|
66
97
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
98
|
+
const content = fs.readFileSync(configPath, "utf8");
|
|
99
|
+
const schemaMatch = content.match(/schema:\s*["'](.+?)["']/);
|
|
100
|
+
if (schemaMatch && schemaMatch[1]) {
|
|
101
|
+
const schemaFull = path.resolve(path.dirname(configPath), schemaMatch[1]);
|
|
102
|
+
if (!fs.existsSync(schemaFull)) {
|
|
103
|
+
return { ok: false, msg: `Schema not found: ${schemaMatch[1]} in ${configPath}` };
|
|
72
104
|
}
|
|
105
|
+
}
|
|
73
106
|
} catch (e) {
|
|
74
|
-
|
|
107
|
+
return { ok: false, msg: `Config parse error in ${configPath}` };
|
|
75
108
|
}
|
|
76
|
-
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return { ok: true, config: configs };
|
|
77
112
|
}
|
|
78
113
|
|
|
79
114
|
/* =============================================================
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
⚙️ SAFE STEP RUNNER
|
|
116
|
+
============================================================= */
|
|
117
|
+
function runStep(args, label) {
|
|
118
|
+
return new Promise((resolve) => {
|
|
119
|
+
startLoading(`${T.pink}${label}${T.reset}`);
|
|
120
|
+
let localErr = false;
|
|
121
|
+
|
|
122
|
+
const child = spawn("npx", args, { shell: true, stdio: ["inherit", "pipe", "pipe"] });
|
|
123
|
+
|
|
124
|
+
child.stdout.on("data", (data) => {
|
|
125
|
+
const out = data.toString();
|
|
126
|
+
if (!out.includes('Pulling schema')) {
|
|
127
|
+
stopLoading();
|
|
128
|
+
process.stdout.write(`${T.gray}${out}${T.reset}`);
|
|
129
|
+
}
|
|
130
|
+
if (/error|failed|ENOTFOUND/i.test(out)) localErr = true;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
child.stderr.on("data", (data) => {
|
|
134
|
+
stopLoading();
|
|
135
|
+
process.stderr.write(`${T.red}${T.bold}✖ ${data}${T.reset}`);
|
|
136
|
+
localErr = true;
|
|
102
137
|
});
|
|
138
|
+
|
|
139
|
+
child.on("close", (code) => {
|
|
140
|
+
stopLoading();
|
|
141
|
+
resolve(code === 0 && !localErr);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
103
144
|
}
|
|
104
145
|
|
|
105
146
|
/* =============================================================
|
|
106
|
-
|
|
107
|
-
|
|
147
|
+
🔁 ENGINE WORKFLOW
|
|
148
|
+
============================================================= */
|
|
108
149
|
let isRunning = false;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
]
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
150
|
+
let hasError = false;
|
|
151
|
+
|
|
152
|
+
async function triggerEngine(event) {
|
|
153
|
+
if (isRunning) return;
|
|
154
|
+
isRunning = true;
|
|
155
|
+
|
|
156
|
+
if (!hasError) console.clear();
|
|
157
|
+
console.log(`\n${T.bg_dark} ${rainbow(" DRIZZLE-AUTO v2026 ")} ${T.reset}`);
|
|
158
|
+
console.log(`${T.magenta}●${T.reset} ${T.bold}Event:${T.reset} ${T.cyan}${event}${T.reset}\n`);
|
|
159
|
+
|
|
160
|
+
const audit = justifyStructure();
|
|
161
|
+
if (!audit.ok) {
|
|
162
|
+
console.log(`${T.red}${T.bold}🛑 CRITICAL FAILURE:${T.reset} ${audit.msg}`);
|
|
163
|
+
hasError = true; isRunning = false; return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const steps = [
|
|
167
|
+
{ name: "Confirming Integrity", args: ["drizzle-kit", "check"] },
|
|
168
|
+
{ name: "Generating Migrations", args: ["drizzle-kit", "generate"] },
|
|
169
|
+
{ name: "Pushing to Database", args: ["drizzle-kit", "push"] }
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
for (const step of steps) {
|
|
173
|
+
const success = await runStep(step.args, step.name);
|
|
174
|
+
if (!success) {
|
|
175
|
+
console.log(`\n${T.red}${T.bold}✖ PIPELINE CRASHED AT [${step.name.toUpperCase()}]${T.reset}`);
|
|
176
|
+
hasError = true; isRunning = false; return;
|
|
136
177
|
}
|
|
178
|
+
}
|
|
137
179
|
|
|
138
|
-
|
|
139
|
-
|
|
180
|
+
hasError = false;
|
|
181
|
+
console.log(`\n${T.lime}${T.bold}✔ SYSTEM JUSTIFIED & SYNCED${T.reset}`);
|
|
182
|
+
console.log(`${T.gray}Waiting for next server-side change...${T.reset}\n`);
|
|
183
|
+
isRunning = false;
|
|
140
184
|
}
|
|
141
185
|
|
|
142
186
|
/* =============================================================
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
persistent: true,
|
|
152
|
-
ignoreInitial: true,
|
|
153
|
-
usePolling: true,
|
|
154
|
-
interval: 300
|
|
155
|
-
});
|
|
187
|
+
👀 WATCHER & GLOBAL CRASH PROTECTION
|
|
188
|
+
============================================================= */
|
|
189
|
+
chokidar.watch(".", {
|
|
190
|
+
ignored: [/node_modules/, /\.git/, /\.next/, /dist/],
|
|
191
|
+
ignoreInitial: true,
|
|
192
|
+
usePolling: true,
|
|
193
|
+
interval: 300
|
|
194
|
+
}).on("all", (e, f) => triggerEngine(`${e.toUpperCase()} -> ${path.basename(f)}`));
|
|
156
195
|
|
|
157
|
-
|
|
158
|
-
startWorkflow(`${event.toUpperCase()} -> ${path.basename(file)}`);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// Initial startup audit
|
|
162
|
-
startWorkflow("Initial System Audit");
|
|
196
|
+
triggerEngine("Initial Audit");
|
|
163
197
|
|
|
164
|
-
// Crash Protection
|
|
165
198
|
process.on("uncaughtException", (err) => {
|
|
166
|
-
|
|
167
|
-
|
|
199
|
+
stopLoading();
|
|
200
|
+
console.log(`\n${T.red}${T.bold}🛡️ PROTECTIVE SHIELD:${T.reset} ${err.message}`);
|
|
201
|
+
isRunning = false;
|
|
168
202
|
});
|
|
203
|
+
|
|
204
|
+
process.on("SIGINT", () => {
|
|
205
|
+
stopLoading();
|
|
206
|
+
console.log(`\n${T.yellow}Shutting down Drizzle-Auto...${T.reset}`);
|
|
207
|
+
process.exit();
|
|
208
|
+
});
|