meksus 0.3.0 → 0.3.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/package.json +1 -1
- package/src/auth.mjs +5 -6
- package/src/hooks.mjs +23 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meksus",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "M.E.K.S.U.S. CLI: see what your AI coding agents (Claude Code) and builds are doing, live, and get Discord alerts when they fail or need you. Status only: code, prompts and output never leave your machine.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"meksus",
|
package/src/auth.mjs
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// typed, pasted or shown:
|
|
5
5
|
// 1. ask the ingest Worker where Supabase lives (/v1/cli/config: public values only)
|
|
6
6
|
// 2. listen on http://127.0.0.1:<random port> for one callback
|
|
7
|
-
// 3. open <supabase>/auth/v1/authorize
|
|
8
|
-
//
|
|
7
|
+
// 3. open https://<app>/cli-callback?challenge=…, which forwards to <supabase>/auth/v1/authorize (GitHub,
|
|
8
|
+
// PKCE). The browser comes back to the same static page, which forwards ?code= to the local listener. The code is
|
|
9
9
|
// useless without this process's verifier, which never leaves it.
|
|
10
10
|
// 4. exchange code + verifier for a session; keep it in config.json (0600)
|
|
11
11
|
// Access tokens last an hour; getAccessToken() refreshes them (rotating refresh token) when needed.
|
|
@@ -55,10 +55,9 @@ export async function login({ noBrowser = false } = {}) {
|
|
|
55
55
|
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
56
56
|
const port = server.address().port;
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
})}`;
|
|
58
|
+
// The browser starts at the app's own /cli-callback page, which forwards to GitHub sign-in (through
|
|
59
|
+
// Supabase Auth) and later hands the code back here. Only public values travel: port, state, challenge.
|
|
60
|
+
const authorize = `${cfg.app_url.replace(/\/$/, "")}/cli-callback?${new URLSearchParams({ port: String(port), state, challenge })}`;
|
|
62
61
|
|
|
63
62
|
console.log("\n Sign in to M.E.K.S.U.S. with GitHub\n");
|
|
64
63
|
console.log(` Open: ${authorize}\n`);
|
package/src/hooks.mjs
CHANGED
|
@@ -132,9 +132,29 @@ function settingsPath(cwd) {
|
|
|
132
132
|
return join(d, ".claude", "settings.local.json");
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
// Reads the settings file, or explains (and changes nothing) when it isn't valid JSON — often two
|
|
136
|
+
// { … } blocks pasted one after the other, which Claude Code can't read either.
|
|
137
|
+
function readSettings(file) {
|
|
138
|
+
if (!existsSync(file)) return {};
|
|
139
|
+
const text = readFileSync(file, "utf8");
|
|
140
|
+
try {
|
|
141
|
+
const value = JSON.parse(text);
|
|
142
|
+
if (value && typeof value === "object" && !Array.isArray(value)) return value;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
const at = /line (\d+)/.exec(error.message)?.[1];
|
|
145
|
+
console.error(`✖ ${file} isn't valid JSON${at ? ` (line ${at})` : ""}, so nothing was changed.`);
|
|
146
|
+
if (/after JSON/.test(error.message)) console.error(" It holds more than one { … } block. Merge them into one object, then run this again.");
|
|
147
|
+
console.error(" Claude Code can't read this file either until it's fixed.");
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
console.error(`✖ ${file} should hold one JSON object, so nothing was changed.`);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
135
154
|
export function install(cwd = process.cwd()) {
|
|
136
155
|
const file = settingsPath(cwd);
|
|
137
|
-
const settings =
|
|
156
|
+
const settings = readSettings(file);
|
|
157
|
+
if (!settings) return 1;
|
|
138
158
|
settings.hooks ??= {};
|
|
139
159
|
const command = `node "${CLI}" hook`;
|
|
140
160
|
for (const event of EVENTS) {
|
|
@@ -155,7 +175,8 @@ export function install(cwd = process.cwd()) {
|
|
|
155
175
|
export function uninstall(cwd = process.cwd()) {
|
|
156
176
|
const file = settingsPath(cwd);
|
|
157
177
|
if (!existsSync(file)) { console.log("No hooks file here."); return 0; }
|
|
158
|
-
const settings =
|
|
178
|
+
const settings = readSettings(file);
|
|
179
|
+
if (!settings) return 1;
|
|
159
180
|
for (const event of Object.keys(settings.hooks ?? {})) {
|
|
160
181
|
settings.hooks[event] = settings.hooks[event]
|
|
161
182
|
.map((g) => ({ ...g, hooks: (g.hooks ?? []).filter((h) => !String(h.command).includes(MARK)) }))
|