drizzle-auto 1.0.8 → 1.0.9
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 +71 -86
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -5,32 +5,29 @@ const path = require("path");
|
|
|
5
5
|
const chokidar = require("chokidar");
|
|
6
6
|
const { spawn } = require("child_process");
|
|
7
7
|
|
|
8
|
-
/*
|
|
9
|
-
🎨
|
|
10
|
-
|
|
8
|
+
/* =======================
|
|
9
|
+
🎨 NeonPulse Colors
|
|
10
|
+
======================= */
|
|
11
11
|
const COLORS = ["\x1b[31m","\x1b[32m","\x1b[33m","\x1b[34m","\x1b[35m","\x1b[36m"];
|
|
12
12
|
const RESET = "\x1b[0m";
|
|
13
13
|
const BOLD = "\x1b[1m";
|
|
14
14
|
const DIM = "\x1b[90m";
|
|
15
|
-
|
|
16
15
|
let colorIndex = 0;
|
|
17
16
|
const nextColor = () => COLORS[colorIndex++ % COLORS.length];
|
|
18
|
-
const rainbow =
|
|
17
|
+
const rainbow = text => text.split("").map(c => `${nextColor()}${c}`).join("") + RESET;
|
|
19
18
|
|
|
20
|
-
/*
|
|
21
|
-
⏳
|
|
22
|
-
|
|
23
|
-
const
|
|
19
|
+
/* =======================
|
|
20
|
+
⏳ Spinner
|
|
21
|
+
======================= */
|
|
22
|
+
const FRAMES = ["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];
|
|
24
23
|
let spinIndex = 0;
|
|
25
|
-
let spinnerInterval;
|
|
26
|
-
|
|
27
|
-
function startSpinner(text) {
|
|
24
|
+
let spinnerInterval = null;
|
|
25
|
+
function startSpinner(msg) {
|
|
28
26
|
stopSpinner();
|
|
29
27
|
spinnerInterval = setInterval(() => {
|
|
30
|
-
process.stdout.write(`\r${nextColor()}${
|
|
28
|
+
process.stdout.write(`\r${nextColor()}${FRAMES[spinIndex++ % FRAMES.length]} ${msg}${RESET}`);
|
|
31
29
|
}, 80);
|
|
32
30
|
}
|
|
33
|
-
|
|
34
31
|
function stopSpinner() {
|
|
35
32
|
if (spinnerInterval) {
|
|
36
33
|
clearInterval(spinnerInterval);
|
|
@@ -39,109 +36,99 @@ function stopSpinner() {
|
|
|
39
36
|
}
|
|
40
37
|
}
|
|
41
38
|
|
|
42
|
-
/*
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (init && fs.existsSync(path.join(init, "package.json"))) return init;
|
|
48
|
-
let cwd = process.cwd();
|
|
49
|
-
if (cwd.includes("node_modules")) cwd = cwd.split(`node_modules${path.sep}`)[0];
|
|
50
|
-
return cwd;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const projectRoot = getProjectRoot();
|
|
54
|
-
const pkgPath = path.join(projectRoot, "package.json");
|
|
39
|
+
/* =======================
|
|
40
|
+
🧠 Project Root + Package.json
|
|
41
|
+
======================= */
|
|
42
|
+
const PROJECT_ROOT = process.env.INIT_CWD || process.cwd();
|
|
43
|
+
const PKG_PATH = path.join(PROJECT_ROOT, "package.json");
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
function injectTeaScript() {
|
|
60
|
-
if (!fs.existsSync(pkgPath)) return;
|
|
61
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
45
|
+
function addTeaScript() {
|
|
46
|
+
if (!fs.existsSync(PKG_PATH)) return;
|
|
47
|
+
const pkg = JSON.parse(fs.readFileSync(PKG_PATH, "utf8"));
|
|
62
48
|
pkg.scripts ||= {};
|
|
63
49
|
if (!pkg.scripts.tea) {
|
|
64
50
|
pkg.scripts.tea = "drizzle-auto";
|
|
65
|
-
fs.writeFileSync(
|
|
66
|
-
console.log(
|
|
51
|
+
fs.writeFileSync(PKG_PATH, JSON.stringify(pkg, null, 2));
|
|
52
|
+
console.log(`⚡ tea script added → npm run tea`);
|
|
67
53
|
}
|
|
68
54
|
}
|
|
69
55
|
|
|
70
|
-
/*
|
|
71
|
-
🧪
|
|
72
|
-
|
|
56
|
+
/* =======================
|
|
57
|
+
🧪 Infra Audit
|
|
58
|
+
======================= */
|
|
73
59
|
function auditInfra() {
|
|
74
60
|
const results = [];
|
|
61
|
+
|
|
62
|
+
// Drizzle config
|
|
75
63
|
const configFile = ["ts","js","mjs","mts"].map(ext => `drizzle.config.${ext}`)
|
|
76
|
-
|
|
64
|
+
.find(f => fs.existsSync(path.join(PROJECT_ROOT, f)));
|
|
77
65
|
results.push({ name: "Drizzle Config", ok: !!configFile });
|
|
78
66
|
|
|
67
|
+
// Schema path
|
|
79
68
|
if (configFile) {
|
|
80
69
|
try {
|
|
81
|
-
const
|
|
82
|
-
const match =
|
|
70
|
+
const cfg = fs.readFileSync(path.join(PROJECT_ROOT, configFile), "utf8");
|
|
71
|
+
const match = cfg.match(/schema:\s*["'](.+?)["']/);
|
|
83
72
|
if (match) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
73
|
+
results.push({
|
|
74
|
+
name: `Schema (${match[1]})`,
|
|
75
|
+
ok: fs.existsSync(path.join(PROJECT_ROOT, match[1]))
|
|
76
|
+
});
|
|
77
|
+
} else results.push({ name: "Schema Path", ok: false });
|
|
89
78
|
} catch {
|
|
90
|
-
results.push({ name: "Config
|
|
79
|
+
results.push({ name: "Config Readable", ok: false });
|
|
91
80
|
}
|
|
92
81
|
}
|
|
93
82
|
|
|
94
|
-
|
|
95
|
-
results.push({ name: "
|
|
83
|
+
// Essentials
|
|
84
|
+
results.push({ name: ".env", ok: fs.existsSync(path.join(PROJECT_ROOT, ".env")) });
|
|
85
|
+
results.push({ name: "node_modules", ok: fs.existsSync(path.join(PROJECT_ROOT, "node_modules")) });
|
|
96
86
|
|
|
97
87
|
const missing = results.filter(r => !r.ok).map(r => r.name);
|
|
98
88
|
return { ok: missing.length === 0, missing };
|
|
99
89
|
}
|
|
100
90
|
|
|
101
|
-
/*
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
function
|
|
105
|
-
return new Promise(
|
|
91
|
+
/* =======================
|
|
92
|
+
⚡ Run npx command
|
|
93
|
+
======================= */
|
|
94
|
+
function runCmd(cmd) {
|
|
95
|
+
return new Promise(resolve => {
|
|
106
96
|
let failed = false;
|
|
107
97
|
startSpinner(`npx ${cmd.join(" ")}`);
|
|
108
98
|
const p = spawn("npx", cmd, { shell: true });
|
|
109
|
-
|
|
110
99
|
p.stdout.on("data", d => {
|
|
111
100
|
stopSpinner();
|
|
112
101
|
process.stdout.write(DIM + d.toString() + RESET);
|
|
113
102
|
if (/error|failed/i.test(d)) failed = true;
|
|
114
103
|
});
|
|
115
|
-
|
|
116
104
|
p.stderr.on("data", d => {
|
|
117
105
|
stopSpinner();
|
|
118
106
|
process.stderr.write("\x1b[31m" + d + RESET);
|
|
119
107
|
failed = true;
|
|
120
108
|
});
|
|
121
|
-
|
|
122
109
|
p.on("close", code => resolve(code === 0 && !failed));
|
|
123
110
|
});
|
|
124
111
|
}
|
|
125
112
|
|
|
126
|
-
/*
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
let
|
|
113
|
+
/* =======================
|
|
114
|
+
🏁 Workflow
|
|
115
|
+
======================= */
|
|
116
|
+
let running = false;
|
|
130
117
|
let hasError = false;
|
|
131
118
|
|
|
132
119
|
async function workflow(trigger) {
|
|
133
|
-
if (
|
|
134
|
-
|
|
120
|
+
if (running) return;
|
|
121
|
+
running = true;
|
|
135
122
|
|
|
136
123
|
if (!hasError) console.clear();
|
|
137
|
-
console.log(`\n${nextColor()}⚡ ${trigger}${RESET}`);
|
|
124
|
+
console.log(`\n${nextColor()}⚡ Trigger → ${trigger}${RESET}`);
|
|
138
125
|
|
|
139
126
|
const audit = auditInfra();
|
|
140
127
|
if (!audit.ok) {
|
|
141
128
|
console.log("\n\x1b[31m❌ Infra not ready\x1b[0m");
|
|
142
129
|
audit.missing.forEach(m => console.log(DIM + "• " + m + RESET));
|
|
143
130
|
hasError = true;
|
|
144
|
-
|
|
131
|
+
running = false;
|
|
145
132
|
return;
|
|
146
133
|
}
|
|
147
134
|
|
|
@@ -151,40 +138,38 @@ async function workflow(trigger) {
|
|
|
151
138
|
["drizzle-kit", "push"]
|
|
152
139
|
];
|
|
153
140
|
|
|
154
|
-
for (const
|
|
155
|
-
if (!(await
|
|
141
|
+
for (const step of steps) {
|
|
142
|
+
if (!(await runCmd(step))) {
|
|
156
143
|
console.log("\n\x1b[31m💀 Pipeline crashed\x1b[0m");
|
|
157
144
|
hasError = true;
|
|
158
|
-
|
|
145
|
+
running = false;
|
|
159
146
|
return;
|
|
160
147
|
}
|
|
161
148
|
}
|
|
162
149
|
|
|
163
150
|
hasError = false;
|
|
164
151
|
console.log("\n\x1b[32m✨ Drizzle synced\x1b[0m");
|
|
165
|
-
setTimeout(() =>
|
|
152
|
+
setTimeout(() => running = false, 1000);
|
|
166
153
|
}
|
|
167
154
|
|
|
168
|
-
/*
|
|
155
|
+
/* =======================
|
|
169
156
|
👀 Watcher
|
|
170
|
-
|
|
171
|
-
chokidar.watch(
|
|
157
|
+
======================= */
|
|
158
|
+
chokidar.watch(PROJECT_ROOT, {
|
|
172
159
|
ignored: [/node_modules/, /\.git/, /\.next/, /dist/],
|
|
173
160
|
ignoreInitial: true,
|
|
174
161
|
usePolling: true,
|
|
175
162
|
interval: 300
|
|
176
|
-
}).on("all", (e, f) => workflow(`${e.toUpperCase()} → ${
|
|
177
|
-
|
|
178
|
-
/*
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
process.exit(0);
|
|
184
|
-
}
|
|
163
|
+
}).on("all", (e, f) => workflow(`${e.toUpperCase()} → ${path.basename(f)}`));
|
|
164
|
+
|
|
165
|
+
/* =======================
|
|
166
|
+
🚀 Init
|
|
167
|
+
======================= */
|
|
168
|
+
addTeaScript(); // inject tea script automatically
|
|
169
|
+
workflow("Initial Audit");
|
|
185
170
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
171
|
+
process.on("uncaughtException", err => {
|
|
172
|
+
stopSpinner();
|
|
173
|
+
console.log("\x1b[31m🔥 Crash:\x1b[0m", err.message);
|
|
174
|
+
running = false;
|
|
175
|
+
});
|