drizzle-auto 1.0.24 β 1.1.1
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 +119 -67
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -6,124 +6,176 @@ const chokidar = require("chokidar");
|
|
|
6
6
|
const { spawn } = require("child_process");
|
|
7
7
|
|
|
8
8
|
/* =========================
|
|
9
|
-
|
|
9
|
+
π¨ COLORS (clean & pro)
|
|
10
10
|
========================= */
|
|
11
|
-
const
|
|
12
|
-
const PKG = path.join(ROOT, "package.json");
|
|
13
|
-
|
|
14
|
-
/* =========================
|
|
15
|
-
π¨ COLORS
|
|
16
|
-
========================= */
|
|
17
|
-
const colors = {
|
|
11
|
+
const C = {
|
|
18
12
|
reset: "\x1b[0m",
|
|
19
|
-
|
|
13
|
+
dim: "\x1b[2m",
|
|
14
|
+
bold: "\x1b[1m",
|
|
15
|
+
cyan: "\x1b[36m",
|
|
20
16
|
green: "\x1b[32m",
|
|
21
17
|
yellow: "\x1b[33m",
|
|
22
|
-
|
|
18
|
+
red: "\x1b[31m",
|
|
23
19
|
magenta: "\x1b[35m",
|
|
24
20
|
};
|
|
25
21
|
|
|
22
|
+
const log = {
|
|
23
|
+
info: (m) => console.log(`${C.cyan}βΉ ${m}${C.reset}`),
|
|
24
|
+
ok: (m) => console.log(`${C.green}β ${m}${C.reset}`),
|
|
25
|
+
warn: (m) => console.log(`${C.yellow}β ${m}${C.reset}`),
|
|
26
|
+
err: (m) => console.log(`${C.red}β ${m}${C.reset}`),
|
|
27
|
+
trig: (m) => console.log(`${C.magenta}β‘ ${m}${C.reset}`),
|
|
28
|
+
};
|
|
29
|
+
|
|
26
30
|
/* =========================
|
|
27
|
-
|
|
31
|
+
π§ PROJECT ROOT
|
|
28
32
|
========================= */
|
|
29
|
-
|
|
33
|
+
const ROOT = process.cwd();
|
|
34
|
+
const PKG = path.join(ROOT, "package.json");
|
|
35
|
+
|
|
36
|
+
/* =========================
|
|
37
|
+
π§© SCRIPT INJECTOR
|
|
38
|
+
========================= */
|
|
39
|
+
function injectScript() {
|
|
30
40
|
if (!fs.existsSync(PKG)) return;
|
|
41
|
+
|
|
31
42
|
const pkg = JSON.parse(fs.readFileSync(PKG, "utf8"));
|
|
32
43
|
pkg.scripts ||= {};
|
|
44
|
+
|
|
33
45
|
if (!pkg.scripts.tea) {
|
|
34
46
|
pkg.scripts.tea = "drizzle-auto";
|
|
35
47
|
fs.writeFileSync(PKG, JSON.stringify(pkg, null, 2));
|
|
36
|
-
|
|
48
|
+
log.ok("Added script β npm run tea");
|
|
37
49
|
}
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
/* =========================
|
|
41
|
-
|
|
53
|
+
π FIND DRIZZLE CONFIG
|
|
54
|
+
(js | mjs | ts | mts)
|
|
42
55
|
========================= */
|
|
43
56
|
function findDrizzleConfig() {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let schema = null;
|
|
52
|
-
try {
|
|
53
|
-
const content = fs.readFileSync(found, "utf8");
|
|
54
|
-
const match = content.match(/schema:\s*["'](.+?)["']/);
|
|
55
|
-
if (match) schema = path.join(ROOT, match[1]);
|
|
56
|
-
} catch {}
|
|
57
|
-
|
|
58
|
-
if (schema && !fs.existsSync(schema)) {
|
|
59
|
-
console.log(`${colors.red}β Schema file missing: ${schema}${colors.reset}`);
|
|
60
|
-
return null;
|
|
57
|
+
const exts = ["js", "mjs", "ts", "mts"];
|
|
58
|
+
for (const e of exts) {
|
|
59
|
+
const p = path.join(ROOT, `drizzle.config.${e}`);
|
|
60
|
+
if (fs.existsSync(p)) return p;
|
|
61
61
|
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
/* =========================
|
|
66
|
+
π FILE FILTER (ALL TYPES)
|
|
67
|
+
========================= */
|
|
68
|
+
const WATCH_EXTS = [
|
|
69
|
+
".js", ".mjs", ".cjs",
|
|
70
|
+
".ts", ".mts",
|
|
71
|
+
".jsx", ".tsx",
|
|
72
|
+
".sql"
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
function isValidFile(file) {
|
|
76
|
+
return WATCH_EXTS.includes(path.extname(file));
|
|
64
77
|
}
|
|
65
78
|
|
|
66
79
|
/* =========================
|
|
67
|
-
|
|
80
|
+
βοΈ SAFE SPAWN (NO SHELL)
|
|
68
81
|
========================= */
|
|
69
|
-
function
|
|
70
|
-
return new Promise(resolve => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
p.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
function exec(cmd, args = []) {
|
|
83
|
+
return new Promise((resolve) => {
|
|
84
|
+
const p = spawn(cmd, args, { stdio: "inherit" });
|
|
85
|
+
|
|
86
|
+
p.on("error", (e) => {
|
|
87
|
+
log.err(`Process error: ${e.message}`);
|
|
88
|
+
resolve(false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
p.on("close", (code) => {
|
|
92
|
+
resolve(code === 0);
|
|
77
93
|
});
|
|
78
|
-
p.on("close", code => resolve(code === 0 && !failed));
|
|
79
94
|
});
|
|
80
95
|
}
|
|
81
96
|
|
|
82
97
|
/* =========================
|
|
83
|
-
|
|
98
|
+
π‘οΈ CRASH PROTECTION
|
|
99
|
+
========================= */
|
|
100
|
+
process.on("uncaughtException", (e) => {
|
|
101
|
+
log.err(`Crash prevented: ${e.message}`);
|
|
102
|
+
});
|
|
103
|
+
process.on("unhandledRejection", (e) => {
|
|
104
|
+
log.err(`Promise rejected: ${e}`);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
/* =========================
|
|
108
|
+
π PIPELINE (DEV SAFE)
|
|
84
109
|
========================= */
|
|
85
|
-
let
|
|
110
|
+
let running = false;
|
|
111
|
+
let lastPush = 0;
|
|
112
|
+
|
|
113
|
+
const DEV_MODE = process.argv.includes("--dev");
|
|
114
|
+
const PUSH_COOLDOWN = DEV_MODE ? 120_000 : 30_000; // safer in dev
|
|
86
115
|
|
|
87
116
|
async function pipeline(trigger) {
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
117
|
+
if (running) return;
|
|
118
|
+
running = true;
|
|
119
|
+
|
|
120
|
+
log.trig(`Trigger β ${trigger}`);
|
|
91
121
|
|
|
92
|
-
const
|
|
93
|
-
if (!
|
|
94
|
-
|
|
122
|
+
const config = findDrizzleConfig();
|
|
123
|
+
if (!config) {
|
|
124
|
+
log.warn("No drizzle.config found");
|
|
125
|
+
running = false;
|
|
95
126
|
return;
|
|
96
127
|
}
|
|
97
128
|
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
if (!
|
|
101
|
-
|
|
102
|
-
|
|
129
|
+
log.info("Running drizzle generateβ¦");
|
|
130
|
+
const gen = await exec("npx", ["drizzle-kit", "generate"]);
|
|
131
|
+
if (!gen) {
|
|
132
|
+
log.err("Generate failed β watching continues");
|
|
133
|
+
running = false;
|
|
103
134
|
return;
|
|
104
135
|
}
|
|
105
136
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
busy = false;
|
|
137
|
+
const now = Date.now();
|
|
138
|
+
if (now - lastPush < PUSH_COOLDOWN) {
|
|
139
|
+
log.warn("Push skipped (cooldown)");
|
|
140
|
+
running = false;
|
|
111
141
|
return;
|
|
112
142
|
}
|
|
113
143
|
|
|
114
|
-
|
|
115
|
-
|
|
144
|
+
log.info("Running drizzle pushβ¦");
|
|
145
|
+
lastPush = now;
|
|
146
|
+
|
|
147
|
+
const push = await exec("npx", ["drizzle-kit", "push"]);
|
|
148
|
+
if (!push) {
|
|
149
|
+
log.err("Push failed β DB untouched, server alive");
|
|
150
|
+
running = false;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
log.ok("Drizzle fully synced");
|
|
155
|
+
running = false;
|
|
116
156
|
}
|
|
117
157
|
|
|
118
158
|
/* =========================
|
|
119
|
-
|
|
159
|
+
π WATCHER (ALL FILES)
|
|
120
160
|
========================= */
|
|
121
|
-
|
|
161
|
+
injectScript();
|
|
122
162
|
pipeline("Initial");
|
|
123
163
|
|
|
164
|
+
log.info(`Watching files (${DEV_MODE ? "DEV MODE" : "SAFE MODE"})β¦`);
|
|
165
|
+
|
|
124
166
|
chokidar.watch(ROOT, {
|
|
125
|
-
ignored: [
|
|
167
|
+
ignored: [
|
|
168
|
+
/node_modules/,
|
|
169
|
+
/\.git/,
|
|
170
|
+
/\.next/,
|
|
171
|
+
/dist/,
|
|
172
|
+
/build/
|
|
173
|
+
],
|
|
126
174
|
ignoreInitial: true,
|
|
127
175
|
usePolling: true,
|
|
128
|
-
interval: 300
|
|
129
|
-
}).on("all", (_, file) =>
|
|
176
|
+
interval: 300,
|
|
177
|
+
}).on("all", (_, file) => {
|
|
178
|
+
if (isValidFile(file)) {
|
|
179
|
+
pipeline(path.relative(ROOT, file));
|
|
180
|
+
}
|
|
181
|
+
});
|