fixmind 1.0.4 → 1.0.6
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/README.md +1 -2
- package/dist/dashboard/assets/index-7eTtNl0A.js +14 -0
- package/dist/dashboard/assets/{index-WDmgeIrO.css → index-CePE7dnd.css} +57 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/src/cli-sync.d.ts +4 -0
- package/dist/src/cli-sync.js +196 -0
- package/dist/src/cli-sync.js.map +1 -0
- package/dist/src/cli-utils.d.ts +34 -0
- package/dist/src/cli-utils.js +119 -0
- package/dist/src/cli-utils.js.map +1 -0
- package/dist/src/cli.js +22 -229
- package/dist/src/cli.js.map +1 -1
- package/dist/src/dashboard.js +16 -0
- package/dist/src/dashboard.js.map +1 -1
- package/dist/src/sync-backend.d.ts +44 -0
- package/dist/src/sync-backend.js +279 -0
- package/dist/src/sync-backend.js.map +1 -0
- package/dist/src/sync.d.ts +2 -44
- package/dist/src/sync.js +36 -289
- package/dist/src/sync.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard/assets/index-Bl0HIoQR.js +0 -14
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import dns from "node:dns";
|
|
3
|
+
import http from "node:http";
|
|
4
|
+
import { createClient } from "@supabase/supabase-js";
|
|
5
|
+
// Some networks resolve AAAA records that time out instead of failing fast,
|
|
6
|
+
// which undici's fetch surfaces as an opaque "TypeError: fetch failed".
|
|
7
|
+
// Resolving IPv4 first avoids that hang on Supabase's auth/token calls.
|
|
8
|
+
dns.setDefaultResultOrder("ipv4first");
|
|
9
|
+
const OAUTH_CALLBACK_PORT = 51763;
|
|
10
|
+
const OAUTH_TIMEOUT_MS = 5 * 60 * 1000;
|
|
11
|
+
class MemoryAuthStorage {
|
|
12
|
+
store = new Map();
|
|
13
|
+
getItem(key) {
|
|
14
|
+
return this.store.get(key) ?? null;
|
|
15
|
+
}
|
|
16
|
+
setItem(key, value) {
|
|
17
|
+
this.store.set(key, value);
|
|
18
|
+
}
|
|
19
|
+
removeItem(key) {
|
|
20
|
+
this.store.delete(key);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function openInBrowser(url) {
|
|
24
|
+
const command = process.platform === "win32"
|
|
25
|
+
? `start "" "${url}"`
|
|
26
|
+
: process.platform === "darwin"
|
|
27
|
+
? `open "${url}"`
|
|
28
|
+
: `xdg-open "${url}"`;
|
|
29
|
+
exec(command, () => {
|
|
30
|
+
// Best-effort: if this fails, the printed URL below is the fallback.
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function escapeHtml(value) {
|
|
34
|
+
return value
|
|
35
|
+
.replace(/&/g, "&")
|
|
36
|
+
.replace(/</g, "<")
|
|
37
|
+
.replace(/>/g, ">")
|
|
38
|
+
.replace(/"/g, """);
|
|
39
|
+
}
|
|
40
|
+
function oauthCallbackPage(options) {
|
|
41
|
+
const tint = options.ok ? "124,92,255" : "255,92,114";
|
|
42
|
+
return `<!doctype html>
|
|
43
|
+
<html lang="en">
|
|
44
|
+
<head>
|
|
45
|
+
<meta charset="utf-8">
|
|
46
|
+
<title>Fixmind</title>
|
|
47
|
+
<style>
|
|
48
|
+
:root { color-scheme: dark; }
|
|
49
|
+
body {
|
|
50
|
+
margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center;
|
|
51
|
+
position: relative; overflow: hidden;
|
|
52
|
+
background-color: #08090d; color: #e9ecf4;
|
|
53
|
+
font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
|
|
54
|
+
}
|
|
55
|
+
body::before {
|
|
56
|
+
content: ""; position: absolute; inset: 0; pointer-events: none;
|
|
57
|
+
background-image:
|
|
58
|
+
linear-gradient(to right, rgba(35,40,56,0.6) 1px, transparent 1px),
|
|
59
|
+
linear-gradient(to bottom, rgba(35,40,56,0.6) 1px, transparent 1px);
|
|
60
|
+
background-size: 48px 48px;
|
|
61
|
+
mask-image: radial-gradient(circle at 50% 35%, black, transparent 75%);
|
|
62
|
+
}
|
|
63
|
+
body::after {
|
|
64
|
+
content: ""; position: absolute; left: 50%; top: 0; width: 760px; height: 420px;
|
|
65
|
+
transform: translateX(-50%); pointer-events: none; border-radius: 9999px;
|
|
66
|
+
background: rgba(${tint},0.15); filter: blur(130px);
|
|
67
|
+
}
|
|
68
|
+
.card {
|
|
69
|
+
position: relative; z-index: 1; text-align: center; padding: 2.5rem 3rem; border-radius: 16px;
|
|
70
|
+
border: 1px solid #232838; background: rgba(17,20,27,0.92);
|
|
71
|
+
}
|
|
72
|
+
.icon {
|
|
73
|
+
width: 48px; height: 48px; margin: 0 auto 1.25rem; border-radius: 50%;
|
|
74
|
+
display: flex; align-items: center; justify-content: center; font-size: 22px;
|
|
75
|
+
background: rgba(${tint},0.15);
|
|
76
|
+
color: ${options.ok ? "#7c5cff" : "#ff5c72"};
|
|
77
|
+
}
|
|
78
|
+
h1 {
|
|
79
|
+
font-family: "Space Grotesk", "Inter", sans-serif; font-size: 1.25rem; font-weight: 600;
|
|
80
|
+
margin: 0 0 0.5rem;
|
|
81
|
+
}
|
|
82
|
+
p { margin: 0; color: #828a9c; font-size: 0.95rem; line-height: 1.5; }
|
|
83
|
+
.redirect {
|
|
84
|
+
display: inline-block; margin-top: 1.5rem; padding: 0.6rem 1.5rem; border-radius: 8px;
|
|
85
|
+
background: #7c5cff; color: #08090d; font-weight: 600; font-size: 0.9rem;
|
|
86
|
+
text-decoration: none;
|
|
87
|
+
}
|
|
88
|
+
.brand {
|
|
89
|
+
margin-top: 2rem; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase;
|
|
90
|
+
color: #4b3aae;
|
|
91
|
+
}
|
|
92
|
+
</style>
|
|
93
|
+
</head>
|
|
94
|
+
<body>
|
|
95
|
+
<div class="card">
|
|
96
|
+
<div class="icon">${options.ok ? "✓" : "!"}</div>
|
|
97
|
+
<h1>${options.ok ? "You're signed in" : "Sign in failed"}</h1>
|
|
98
|
+
<p>${escapeHtml(options.message)}</p>
|
|
99
|
+
${options.redirectUrl ? `<a class="redirect" href="${escapeHtml(options.redirectUrl)}">Try again</a>` : ""}
|
|
100
|
+
<div class="brand">Fixmind</div>
|
|
101
|
+
</div>
|
|
102
|
+
</body>
|
|
103
|
+
</html>`;
|
|
104
|
+
}
|
|
105
|
+
function waitForOAuthCode(port, authUrl) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
const server = http.createServer((req, res) => {
|
|
108
|
+
const url = new URL(req.url ?? "/", `http://127.0.0.1:${port}`);
|
|
109
|
+
const code = url.searchParams.get("code");
|
|
110
|
+
const errorDescription = url.searchParams.get("error_description") ?? url.searchParams.get("error");
|
|
111
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
112
|
+
res.end(errorDescription
|
|
113
|
+
? oauthCallbackPage({
|
|
114
|
+
ok: false,
|
|
115
|
+
message: `${errorDescription}. You can close this window and return to the terminal.`,
|
|
116
|
+
redirectUrl: authUrl,
|
|
117
|
+
})
|
|
118
|
+
: oauthCallbackPage({ ok: true, message: "You can close this window and return to the terminal." }));
|
|
119
|
+
clearTimeout(timeout);
|
|
120
|
+
server.close();
|
|
121
|
+
if (errorDescription)
|
|
122
|
+
reject(new Error(`GitHub sign in failed: ${errorDescription}`));
|
|
123
|
+
else if (code)
|
|
124
|
+
resolve(code);
|
|
125
|
+
else
|
|
126
|
+
reject(new Error("No authorization code received from Supabase."));
|
|
127
|
+
});
|
|
128
|
+
const timeout = setTimeout(() => {
|
|
129
|
+
server.close();
|
|
130
|
+
reject(new Error("Timed out waiting for GitHub sign in."));
|
|
131
|
+
}, OAUTH_TIMEOUT_MS);
|
|
132
|
+
server.on("error", (error) => {
|
|
133
|
+
clearTimeout(timeout);
|
|
134
|
+
reject(error);
|
|
135
|
+
});
|
|
136
|
+
server.listen(port, "127.0.0.1");
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
export function createSupabaseBackend(url, anonKey) {
|
|
140
|
+
function client() {
|
|
141
|
+
return createClient(url, anonKey);
|
|
142
|
+
}
|
|
143
|
+
async function withSession(session) {
|
|
144
|
+
const supabase = client();
|
|
145
|
+
const { error } = await supabase.auth.setSession({
|
|
146
|
+
access_token: session.accessToken,
|
|
147
|
+
refresh_token: session.refreshToken,
|
|
148
|
+
});
|
|
149
|
+
if (error)
|
|
150
|
+
throw new Error(`Sync auth error: ${error.message}`);
|
|
151
|
+
return supabase;
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
async signIn(email, password) {
|
|
155
|
+
const supabase = client();
|
|
156
|
+
const { data, error } = await supabase.auth.signInWithPassword({ email, password });
|
|
157
|
+
if (error || !data.session)
|
|
158
|
+
throw new Error(`Sign in failed: ${error?.message ?? "no session"}`);
|
|
159
|
+
return {
|
|
160
|
+
userId: data.user.id,
|
|
161
|
+
accessToken: data.session.access_token,
|
|
162
|
+
refreshToken: data.session.refresh_token,
|
|
163
|
+
};
|
|
164
|
+
},
|
|
165
|
+
async signUp(email, password) {
|
|
166
|
+
const supabase = client();
|
|
167
|
+
const { data, error } = await supabase.auth.signUp({ email, password });
|
|
168
|
+
if (error)
|
|
169
|
+
throw new Error(`Sign up failed: ${error.message}`);
|
|
170
|
+
if (!data.session) {
|
|
171
|
+
throw new Error("Account created. Check your email to confirm it, then run `fixmind login` again.");
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
userId: data.user.id,
|
|
175
|
+
accessToken: data.session.access_token,
|
|
176
|
+
refreshToken: data.session.refresh_token,
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
async signInWithGithub(onAuthUrl) {
|
|
180
|
+
const supabase = createClient(url, anonKey, {
|
|
181
|
+
auth: {
|
|
182
|
+
flowType: "pkce",
|
|
183
|
+
storage: new MemoryAuthStorage(),
|
|
184
|
+
persistSession: false,
|
|
185
|
+
autoRefreshToken: false,
|
|
186
|
+
detectSessionInUrl: false,
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
const redirectTo = `http://127.0.0.1:${OAUTH_CALLBACK_PORT}`;
|
|
190
|
+
const { data, error } = await supabase.auth.signInWithOAuth({
|
|
191
|
+
provider: "github",
|
|
192
|
+
options: { redirectTo, skipBrowserRedirect: true },
|
|
193
|
+
});
|
|
194
|
+
if (error || !data.url)
|
|
195
|
+
throw new Error(`GitHub sign in failed: ${error?.message ?? "no auth URL"}`);
|
|
196
|
+
onAuthUrl?.(data.url);
|
|
197
|
+
openInBrowser(data.url);
|
|
198
|
+
const code = await waitForOAuthCode(OAUTH_CALLBACK_PORT, data.url);
|
|
199
|
+
const { data: exchanged, error: exchangeError } = await supabase.auth.exchangeCodeForSession(code);
|
|
200
|
+
if (exchangeError || !exchanged.session) {
|
|
201
|
+
throw new Error(`GitHub sign in failed: ${exchangeError?.message ?? "no session"}`);
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
userId: exchanged.user.id,
|
|
205
|
+
email: exchanged.user.email ?? "",
|
|
206
|
+
accessToken: exchanged.session.access_token,
|
|
207
|
+
refreshToken: exchanged.session.refresh_token,
|
|
208
|
+
};
|
|
209
|
+
},
|
|
210
|
+
async getEntitlement(session) {
|
|
211
|
+
const supabase = await withSession(session);
|
|
212
|
+
const { data, error } = await supabase
|
|
213
|
+
.from("entitlements")
|
|
214
|
+
.select("plan, status")
|
|
215
|
+
.maybeSingle();
|
|
216
|
+
if (error)
|
|
217
|
+
throw new Error(`Entitlement check failed: ${error.message}`);
|
|
218
|
+
if (!data)
|
|
219
|
+
return undefined;
|
|
220
|
+
return { plan: data.plan, status: data.status };
|
|
221
|
+
},
|
|
222
|
+
async getUserRecord(userId, session) {
|
|
223
|
+
const supabase = await withSession(session);
|
|
224
|
+
const { data, error } = await supabase
|
|
225
|
+
.from("sync_users")
|
|
226
|
+
.select("salt, verifier_ciphertext, verifier_iv")
|
|
227
|
+
.eq("user_id", userId)
|
|
228
|
+
.maybeSingle();
|
|
229
|
+
if (error)
|
|
230
|
+
throw new Error(`Sync lookup failed: ${error.message}`);
|
|
231
|
+
if (!data)
|
|
232
|
+
return undefined;
|
|
233
|
+
return { salt: data.salt, verifierCiphertext: data.verifier_ciphertext, verifierIv: data.verifier_iv };
|
|
234
|
+
},
|
|
235
|
+
async createUserRecord(userId, session, record) {
|
|
236
|
+
const supabase = await withSession(session);
|
|
237
|
+
const { error } = await supabase.from("sync_users").insert({
|
|
238
|
+
user_id: userId,
|
|
239
|
+
salt: record.salt,
|
|
240
|
+
verifier_ciphertext: record.verifierCiphertext,
|
|
241
|
+
verifier_iv: record.verifierIv,
|
|
242
|
+
});
|
|
243
|
+
if (error)
|
|
244
|
+
throw new Error(`Sync setup failed: ${error.message}`);
|
|
245
|
+
},
|
|
246
|
+
async upsertLessons(userId, session, rows) {
|
|
247
|
+
if (rows.length === 0)
|
|
248
|
+
return;
|
|
249
|
+
const supabase = await withSession(session);
|
|
250
|
+
const { error } = await supabase.from("lessons_sync").upsert(rows.map((row) => ({
|
|
251
|
+
user_id: userId,
|
|
252
|
+
lesson_id: row.lessonId,
|
|
253
|
+
ciphertext: row.ciphertext,
|
|
254
|
+
iv: row.iv,
|
|
255
|
+
updated_at: row.updatedAt,
|
|
256
|
+
})));
|
|
257
|
+
if (error)
|
|
258
|
+
throw new Error(`Push failed: ${error.message}`);
|
|
259
|
+
},
|
|
260
|
+
async fetchLessonsSince(userId, session, since) {
|
|
261
|
+
const supabase = await withSession(session);
|
|
262
|
+
const { data, error } = await supabase
|
|
263
|
+
.from("lessons_sync")
|
|
264
|
+
.select("lesson_id, ciphertext, iv, updated_at")
|
|
265
|
+
.eq("user_id", userId)
|
|
266
|
+
.gt("updated_at", since)
|
|
267
|
+
.order("updated_at", { ascending: true });
|
|
268
|
+
if (error)
|
|
269
|
+
throw new Error(`Pull failed: ${error.message}`);
|
|
270
|
+
return (data ?? []).map((row) => ({
|
|
271
|
+
lessonId: row.lesson_id,
|
|
272
|
+
ciphertext: row.ciphertext,
|
|
273
|
+
iv: row.iv,
|
|
274
|
+
updatedAt: row.updated_at,
|
|
275
|
+
}));
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=sync-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-backend.js","sourceRoot":"","sources":["../../src/sync-backend.ts"],"names":[],"mappings":"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"}
|
package/dist/src/sync.d.ts
CHANGED
|
@@ -1,49 +1,7 @@
|
|
|
1
1
|
import type { LessonStore } from "./storage.js";
|
|
2
|
+
import { type SyncBackend } from "./sync-backend.js";
|
|
3
|
+
export type { Entitlement, SessionTokens, SyncBackend, SyncRow, SyncUserRecord } from "./sync-backend.js";
|
|
2
4
|
export declare const PRICING_URL = "https://fixmind.dev/pricing";
|
|
3
|
-
export interface SyncRow {
|
|
4
|
-
lessonId: string;
|
|
5
|
-
ciphertext: string;
|
|
6
|
-
iv: string;
|
|
7
|
-
updatedAt: string;
|
|
8
|
-
}
|
|
9
|
-
export interface Entitlement {
|
|
10
|
-
plan: string;
|
|
11
|
-
status: string;
|
|
12
|
-
}
|
|
13
|
-
export interface SyncUserRecord {
|
|
14
|
-
salt: string;
|
|
15
|
-
verifierCiphertext: string;
|
|
16
|
-
verifierIv: string;
|
|
17
|
-
}
|
|
18
|
-
export interface OAuthSession {
|
|
19
|
-
userId: string;
|
|
20
|
-
email: string;
|
|
21
|
-
accessToken: string;
|
|
22
|
-
refreshToken: string;
|
|
23
|
-
}
|
|
24
|
-
export interface SyncBackend {
|
|
25
|
-
signIn(email: string, password: string): Promise<{
|
|
26
|
-
userId: string;
|
|
27
|
-
refreshToken: string;
|
|
28
|
-
accessToken: string;
|
|
29
|
-
}>;
|
|
30
|
-
signUp(email: string, password: string): Promise<{
|
|
31
|
-
userId: string;
|
|
32
|
-
refreshToken: string;
|
|
33
|
-
accessToken: string;
|
|
34
|
-
}>;
|
|
35
|
-
signInWithGithub(onAuthUrl?: (url: string) => void): Promise<OAuthSession>;
|
|
36
|
-
getEntitlement(session: SessionTokens): Promise<Entitlement | undefined>;
|
|
37
|
-
getUserRecord(userId: string, session: SessionTokens): Promise<SyncUserRecord | undefined>;
|
|
38
|
-
createUserRecord(userId: string, session: SessionTokens, record: SyncUserRecord): Promise<void>;
|
|
39
|
-
upsertLessons(userId: string, session: SessionTokens, rows: SyncRow[]): Promise<void>;
|
|
40
|
-
fetchLessonsSince(userId: string, session: SessionTokens, since: string): Promise<SyncRow[]>;
|
|
41
|
-
}
|
|
42
|
-
export interface SessionTokens {
|
|
43
|
-
accessToken: string;
|
|
44
|
-
refreshToken: string;
|
|
45
|
-
}
|
|
46
|
-
export declare function createSupabaseBackend(url: string, anonKey: string): SyncBackend;
|
|
47
5
|
export interface LoginResult {
|
|
48
6
|
email: string;
|
|
49
7
|
entitled: boolean;
|