drizzle-auto 1.1.4 → 1.1.5
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 +141 -154
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -5,177 +5,164 @@ const { spawn } = require("child_process");
|
|
|
5
5
|
const path = require("path");
|
|
6
6
|
const fs = require("fs");
|
|
7
7
|
|
|
8
|
-
/*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
/* =============================================================
|
|
9
|
+
1. UI & COLOR CONFIGURATION (NeonPulse Style)
|
|
10
|
+
============================================================= */
|
|
11
|
+
const C = {
|
|
12
|
+
reset: "\x1b[0m",
|
|
13
|
+
bold: "\x1b[1m",
|
|
14
|
+
red: "\x1b[31m",
|
|
15
|
+
green: "\x1b[32m",
|
|
16
|
+
yellow: "\x1b[33m",
|
|
17
|
+
blue: "\x1b[34m",
|
|
18
|
+
magenta: "\x1b[35m",
|
|
19
|
+
cyan: "\x1b[36m",
|
|
20
|
+
dim: "\x1b[90m"
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const PALETTE = [C.red, C.green, C.yellow, C.blue, C.magenta, C.cyan];
|
|
16
24
|
let colorIndex = 0;
|
|
17
25
|
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
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
process.
|
|
39
|
-
|
|
27
|
+
/* =============================================================
|
|
28
|
+
2. AUTOMATIC PACKAGE.JSON INJECTION (The "tea" Script)
|
|
29
|
+
============================================================= */
|
|
30
|
+
function injectTeaScript() {
|
|
31
|
+
const pkgPath = path.join(process.cwd(), "package.json");
|
|
32
|
+
if (fs.existsSync(pkgPath)) {
|
|
33
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
34
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
35
|
+
if (!pkg.scripts.tea) {
|
|
36
|
+
pkg.scripts.tea = "drizzle-auto";
|
|
37
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
38
|
+
console.log(`${C.green}✔ Added "tea": "drizzle-auto" to package.json${C.reset}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
/*
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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]}` };
|
|
43
|
+
/* =============================================================
|
|
44
|
+
3. DEEP INFRASTRUCTURE JUSTIFICATION (Recursive Search)
|
|
45
|
+
============================================================= */
|
|
46
|
+
function findConfig(dir = process.cwd()) {
|
|
47
|
+
const files = fs.readdirSync(dir);
|
|
48
|
+
for (const file of files) {
|
|
49
|
+
const fullPath = path.join(dir, file);
|
|
50
|
+
if (IGNORED_REGEX.test(fullPath)) continue;
|
|
51
|
+
|
|
52
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
53
|
+
const found = findConfig(fullPath);
|
|
54
|
+
if (found) return found;
|
|
55
|
+
} else if (/^drizzle\.config\.(js|mjs|cjs|ts|mts)$/.test(file)) {
|
|
56
|
+
return fullPath;
|
|
57
|
+
}
|
|
66
58
|
}
|
|
67
|
-
|
|
68
|
-
return { ok: false, msg: "Failed to read or parse config file." };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return { ok: true };
|
|
59
|
+
return null;
|
|
72
60
|
}
|
|
73
61
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
child.stderr.on("data", (data) => {
|
|
93
|
-
const err = data.toString();
|
|
94
|
-
stopSpinner();
|
|
95
|
-
process.stderr.write(`\x1b[31m${err}${RESET}`);
|
|
96
|
-
hasError = true;
|
|
97
|
-
});
|
|
62
|
+
function justifyInfrastructure() {
|
|
63
|
+
const configPath = findConfig();
|
|
64
|
+
if (!configPath) return { ok: false, msg: "Missing drizzle.config.*" };
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const content = fs.readFileSync(configPath, "utf8");
|
|
68
|
+
const schemaMatch = content.match(/schema:\s*["'](.+?)["']/);
|
|
69
|
+
if (schemaMatch && schemaMatch[1]) {
|
|
70
|
+
const schemaPath = path.resolve(path.dirname(configPath), schemaMatch[1]);
|
|
71
|
+
if (!fs.existsSync(schemaPath)) return { ok: false, msg: `Schema missing at ${schemaMatch[1]}` };
|
|
72
|
+
}
|
|
73
|
+
} catch (e) {
|
|
74
|
+
return { ok: false, msg: "Config unreadable" };
|
|
75
|
+
}
|
|
76
|
+
return { ok: true, path: configPath };
|
|
77
|
+
}
|
|
98
78
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
79
|
+
/* =============================================================
|
|
80
|
+
4. SAFE COMMAND EXECUTION (Step-by-Step Chain)
|
|
81
|
+
============================================================= */
|
|
82
|
+
function execute(args, name) {
|
|
83
|
+
return new Promise((resolve) => {
|
|
84
|
+
let hasError = false;
|
|
85
|
+
console.log(`${C.cyan}⏳ ${name}...${C.reset}`);
|
|
86
|
+
|
|
87
|
+
const child = spawn("npx", args, { shell: true, stdio: ["inherit", "pipe", "pipe"] });
|
|
88
|
+
|
|
89
|
+
child.stdout.on("data", (data) => {
|
|
90
|
+
const out = data.toString();
|
|
91
|
+
// Filter noise from Cloud DB pullers
|
|
92
|
+
if (!out.includes('Pulling schema')) process.stdout.write(`${C.dim}${out}${C.reset}`);
|
|
93
|
+
if (/error|failed|ENOTFOUND|ECONNREFUSED/i.test(out)) hasError = true;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
child.stderr.on("data", (data) => {
|
|
97
|
+
process.stderr.write(`${C.red}${data}${C.reset}`);
|
|
98
|
+
hasError = true;
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
child.on("close", (code) => resolve(code === 0 && !hasError));
|
|
102
102
|
});
|
|
103
|
-
});
|
|
104
103
|
}
|
|
105
104
|
|
|
106
|
-
/*
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
/* =============================================================
|
|
106
|
+
5. DYNAMIC WORKFLOW MANAGER
|
|
107
|
+
============================================================= */
|
|
108
|
+
let isRunning = false;
|
|
109
109
|
async function startWorkflow(trigger) {
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
console.log(
|
|
139
|
-
hasActiveError = true;
|
|
140
|
-
isRunning = false;
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
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;
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
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(() => {
|
|
110
|
+
if (isRunning) return;
|
|
111
|
+
isRunning = true;
|
|
112
|
+
|
|
113
|
+
console.log(`\n${nextColor()}⚡ Triggered: ${trigger}${C.reset}`);
|
|
114
|
+
|
|
115
|
+
// Step 2: Justify Files
|
|
116
|
+
const infra = justifyInfrastructure();
|
|
117
|
+
if (!infra.ok) {
|
|
118
|
+
console.log(`${C.red}🛑 Infrastructure Failure: ${infra.msg}${C.reset}`);
|
|
119
|
+
isRunning = false;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Step 3 & 4: Sequence (Generate -> Push)
|
|
124
|
+
const steps = [
|
|
125
|
+
{ name: "Generating Schema", args: ["drizzle-kit", "generate"] },
|
|
126
|
+
{ name: "Pushing to Database", args: ["drizzle-kit", "push"] }
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
for (const step of steps) {
|
|
130
|
+
const ok = await execute(step.args, step.name);
|
|
131
|
+
if (!ok) {
|
|
132
|
+
console.log(`${C.red}${C.bold}✖ Pipeline Halted. Check logs above.${C.reset}`);
|
|
133
|
+
isRunning = false;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
console.log(`${C.green}${C.bold}✨ Success: All steps completed.${C.reset}`);
|
|
158
139
|
isRunning = false;
|
|
159
|
-
console.log(`\n${DIM}🛰️ System justified. Watching for next change...${RESET}`);
|
|
160
|
-
}, 2000);
|
|
161
140
|
}
|
|
162
141
|
|
|
163
|
-
/*
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
142
|
+
/* =============================================================
|
|
143
|
+
6. UNIVERSAL WATCHER & INITIALIZATION
|
|
144
|
+
============================================================= */
|
|
145
|
+
const IGNORED_REGEX = /(node_modules|\.git|\.next|dist)/;
|
|
146
|
+
|
|
147
|
+
injectTeaScript();
|
|
148
|
+
|
|
149
|
+
const watcher = chokidar.watch(".", {
|
|
150
|
+
ignored: IGNORED_REGEX,
|
|
151
|
+
persistent: true,
|
|
152
|
+
ignoreInitial: true,
|
|
153
|
+
usePolling: true,
|
|
154
|
+
interval: 300
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
watcher.on("all", (event, file) => {
|
|
158
|
+
startWorkflow(`${event.toUpperCase()} -> ${path.basename(file)}`);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Initial startup audit
|
|
174
162
|
startWorkflow("Initial System Audit");
|
|
175
163
|
|
|
176
|
-
//
|
|
164
|
+
// Crash Protection
|
|
177
165
|
process.on("uncaughtException", (err) => {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
isRunning = false;
|
|
166
|
+
console.log(`${C.red}🛡️ Shield: ${err.message}${C.reset}`);
|
|
167
|
+
isRunning = false;
|
|
181
168
|
});
|