fakebase-studio 1.0.8 → 1.0.10
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 +4 -0
- package/package.json +7 -3
- package/server/dist/index.d.ts.map +1 -1
- package/server/dist/index.js +2 -0
- package/server/dist/index.js.map +1 -1
- package/server/dist/routes/connections.d.ts.map +1 -1
- package/server/dist/routes/connections.js +2 -0
- package/server/dist/routes/connections.js.map +1 -1
- package/server/dist/routes/queries.d.ts.map +1 -1
- package/server/dist/routes/queries.js +42 -9
- package/server/dist/routes/queries.js.map +1 -1
- package/server/dist/routes/tables.d.ts.map +1 -1
- package/server/dist/routes/tables.js +212 -0
- package/server/dist/routes/tables.js.map +1 -1
- package/server/dist/services/queries.service.d.ts +5 -4
- package/server/dist/services/queries.service.d.ts.map +1 -1
- package/server/dist/services/queries.service.js +90 -21
- package/server/dist/services/queries.service.js.map +1 -1
- package/server/dist/services/telemetry.service.d.ts +2 -0
- package/server/dist/services/telemetry.service.d.ts.map +1 -0
- package/server/dist/services/telemetry.service.js +47 -0
- package/server/dist/services/telemetry.service.js.map +1 -0
- package/server/dist/services/telemetry.service.test.d.ts +2 -0
- package/server/dist/services/telemetry.service.test.d.ts.map +1 -0
- package/server/dist/services/telemetry.service.test.js +62 -0
- package/server/dist/services/telemetry.service.test.js.map +1 -0
- package/ui/dist/assets/index-CSlqQoOe.css +1 -0
- package/ui/dist/assets/index-DFaoPews.js +79 -0
- package/ui/dist/index.html +2 -2
- package/ui/dist/assets/index-C9faKqyl.css +0 -1
- package/ui/dist/assets/index-CTt9CUvp.js +0 -73
|
@@ -8,30 +8,76 @@ async function ensureConfigDir() {
|
|
|
8
8
|
await fs.mkdir(CONFIG_DIR, { recursive: true, mode: 0o700 }).catch(() => { });
|
|
9
9
|
await fs.chmod(CONFIG_DIR, 0o700).catch(() => { });
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
function isValidQuery(q) {
|
|
12
|
+
return (q !== null &&
|
|
13
|
+
typeof q === "object" &&
|
|
14
|
+
"id" in q &&
|
|
15
|
+
"name" in q &&
|
|
16
|
+
"sql" in q &&
|
|
17
|
+
"updatedAt" in q);
|
|
18
|
+
}
|
|
19
|
+
async function loadQueriesMap() {
|
|
12
20
|
try {
|
|
13
21
|
await ensureConfigDir();
|
|
14
22
|
const data = await fs.readFile(QUERIES_FILE, "utf-8");
|
|
15
23
|
const parsed = JSON.parse(data);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
if (Array.isArray(parsed)) {
|
|
25
|
+
// Legacy format (flat array) - return it tagged so callers can migrate
|
|
26
|
+
return { __legacy__: parsed.filter(isValidQuery) };
|
|
27
|
+
}
|
|
28
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
29
|
+
// Legacy format with { queries: [...] }
|
|
30
|
+
if (Array.isArray(parsed.queries)) {
|
|
31
|
+
return { __legacy__: parsed.queries.filter(isValidQuery) };
|
|
32
|
+
}
|
|
33
|
+
// New per-connection format
|
|
34
|
+
const map = {};
|
|
35
|
+
for (const [key, val] of Object.entries(parsed)) {
|
|
36
|
+
if (Array.isArray(val)) {
|
|
37
|
+
map[key] = val.filter(isValidQuery);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return map;
|
|
41
|
+
}
|
|
42
|
+
return {};
|
|
23
43
|
}
|
|
24
44
|
catch {
|
|
25
|
-
return
|
|
45
|
+
return {};
|
|
26
46
|
}
|
|
27
47
|
}
|
|
28
|
-
async function
|
|
48
|
+
async function saveQueriesMap(map) {
|
|
29
49
|
await ensureConfigDir();
|
|
30
|
-
await fs.writeFile(QUERIES_FILE, JSON.stringify(
|
|
50
|
+
await fs.writeFile(QUERIES_FILE, JSON.stringify(map, null, 2), "utf-8");
|
|
31
51
|
await fs.chmod(QUERIES_FILE, 0o600).catch(() => { });
|
|
32
52
|
}
|
|
33
|
-
export async function
|
|
34
|
-
const
|
|
53
|
+
export async function loadQueries(connectionId) {
|
|
54
|
+
const map = await loadQueriesMap();
|
|
55
|
+
// Handle legacy migration: assign old queries to requesting connection
|
|
56
|
+
if ("__legacy__" in map && map.__legacy__.length > 0) {
|
|
57
|
+
const legacyQueries = map.__legacy__;
|
|
58
|
+
delete map.__legacy__;
|
|
59
|
+
map[connectionId] = legacyQueries;
|
|
60
|
+
await saveQueriesMap(map);
|
|
61
|
+
return legacyQueries;
|
|
62
|
+
}
|
|
63
|
+
// Clean up empty legacy key if present
|
|
64
|
+
if ("__legacy__" in map) {
|
|
65
|
+
delete map.__legacy__;
|
|
66
|
+
await saveQueriesMap(map);
|
|
67
|
+
}
|
|
68
|
+
return map[connectionId] ?? [];
|
|
69
|
+
}
|
|
70
|
+
export async function saveQuery(connectionId, id, name, sql) {
|
|
71
|
+
const map = await loadQueriesMap();
|
|
72
|
+
// Migrate legacy if present
|
|
73
|
+
if ("__legacy__" in map && map.__legacy__.length > 0) {
|
|
74
|
+
map[connectionId] = map.__legacy__;
|
|
75
|
+
delete map.__legacy__;
|
|
76
|
+
}
|
|
77
|
+
else if ("__legacy__" in map) {
|
|
78
|
+
delete map.__legacy__;
|
|
79
|
+
}
|
|
80
|
+
const queries = map[connectionId] ?? [];
|
|
35
81
|
const now = Date.now();
|
|
36
82
|
const trimmedName = name.trim() || "Untitled query";
|
|
37
83
|
if (id) {
|
|
@@ -43,7 +89,8 @@ export async function saveQuery(id, name, sql) {
|
|
|
43
89
|
sql: sql.trim(),
|
|
44
90
|
updatedAt: now,
|
|
45
91
|
};
|
|
46
|
-
|
|
92
|
+
map[connectionId] = queries;
|
|
93
|
+
await saveQueriesMap(map);
|
|
47
94
|
return queries[idx];
|
|
48
95
|
}
|
|
49
96
|
}
|
|
@@ -54,25 +101,47 @@ export async function saveQuery(id, name, sql) {
|
|
|
54
101
|
updatedAt: now,
|
|
55
102
|
};
|
|
56
103
|
queries.unshift(newQuery);
|
|
57
|
-
|
|
104
|
+
map[connectionId] = queries;
|
|
105
|
+
await saveQueriesMap(map);
|
|
58
106
|
return newQuery;
|
|
59
107
|
}
|
|
60
|
-
export async function removeQueryById(id) {
|
|
61
|
-
const
|
|
108
|
+
export async function removeQueryById(connectionId, id) {
|
|
109
|
+
const map = await loadQueriesMap();
|
|
110
|
+
if ("__legacy__" in map)
|
|
111
|
+
delete map.__legacy__;
|
|
112
|
+
const queries = map[connectionId];
|
|
113
|
+
if (!queries)
|
|
114
|
+
return false;
|
|
62
115
|
const filtered = queries.filter((q) => q.id !== id);
|
|
63
116
|
if (filtered.length === queries.length)
|
|
64
117
|
return false;
|
|
65
|
-
|
|
118
|
+
map[connectionId] = filtered;
|
|
119
|
+
await saveQueriesMap(map);
|
|
66
120
|
return true;
|
|
67
121
|
}
|
|
68
|
-
export async function updateQueryName(id, name) {
|
|
69
|
-
const
|
|
122
|
+
export async function updateQueryName(connectionId, id, name) {
|
|
123
|
+
const map = await loadQueriesMap();
|
|
124
|
+
if ("__legacy__" in map)
|
|
125
|
+
delete map.__legacy__;
|
|
126
|
+
const queries = map[connectionId];
|
|
127
|
+
if (!queries)
|
|
128
|
+
return null;
|
|
70
129
|
const q = queries.find((x) => x.id === id);
|
|
71
130
|
if (!q)
|
|
72
131
|
return null;
|
|
73
132
|
q.name = name.trim() || q.name;
|
|
74
133
|
q.updatedAt = Date.now();
|
|
75
|
-
|
|
134
|
+
map[connectionId] = queries;
|
|
135
|
+
await saveQueriesMap(map);
|
|
76
136
|
return q;
|
|
77
137
|
}
|
|
138
|
+
export async function removeQueriesByConnectionId(connectionId) {
|
|
139
|
+
const map = await loadQueriesMap();
|
|
140
|
+
if ("__legacy__" in map)
|
|
141
|
+
delete map.__legacy__;
|
|
142
|
+
if (connectionId in map) {
|
|
143
|
+
delete map[connectionId];
|
|
144
|
+
await saveQueriesMap(map);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
78
147
|
//# sourceMappingURL=queries.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.service.js","sourceRoot":"","sources":["../../services/queries.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,MAAM,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"queries.service.js","sourceRoot":"","sources":["../../services/queries.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.service.d.ts","sourceRoot":"","sources":["../../services/telemetry.service.ts"],"names":[],"mappings":"AAuCA,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAYzD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import crypto from "crypto";
|
|
5
|
+
import { createRequire } from "module";
|
|
6
|
+
import { createClient } from "@supabase/supabase-js";
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
const TELEMETRY_URL = "https://eoemfvtnmxikxrzavywj.supabase.co";
|
|
9
|
+
const TELEMETRY_KEY_PUBLIC_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImVvZW1mdnRubXhpa3hyemF2eXdqIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQxNzgxMzIsImV4cCI6MjA4OTc1NDEzMn0.ia8rOpC6np3zoJW2z7Egt1hoy0rULKtJQNVFSvqudR4";
|
|
10
|
+
const supabase = createClient(TELEMETRY_URL, TELEMETRY_KEY_PUBLIC_KEY);
|
|
11
|
+
const CONFIG_DIR = path.join(os.homedir(), ".fakebase-studio");
|
|
12
|
+
const ID_FILE = path.join(CONFIG_DIR, "installation-id");
|
|
13
|
+
async function getInstallationId() {
|
|
14
|
+
try {
|
|
15
|
+
const id = await fs.readFile(ID_FILE, "utf-8");
|
|
16
|
+
return id.trim();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
const id = crypto.randomUUID();
|
|
20
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true });
|
|
21
|
+
await fs.writeFile(ID_FILE, id, "utf-8");
|
|
22
|
+
return id;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function getVersion() {
|
|
26
|
+
try {
|
|
27
|
+
const pkg = require("../../package.json");
|
|
28
|
+
return pkg.version || "unknown";
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return "unknown";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function recordTelemetryPing() {
|
|
35
|
+
try {
|
|
36
|
+
const id = await getInstallationId();
|
|
37
|
+
const version = getVersion();
|
|
38
|
+
await supabase.rpc("upsert_installation", {
|
|
39
|
+
p_id: id,
|
|
40
|
+
p_version: version,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Silently fail -- telemetry must never break the app
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=telemetry.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.service.js","sourceRoot":"","sources":["../../services/telemetry.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,MAAM,aAAa,GAAG,0CAA0C,CAAC;AACjE,MAAM,wBAAwB,GAC5B,kNAAkN,CAAC;AAErN,MAAM,QAAQ,GAAG,YAAY,CAAC,aAAa,EAAE,wBAAwB,CAAC,CAAC;AAEvE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAEzD,KAAK,UAAU,iBAAiB;IAC9B,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAC/B,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAC1C,OAAO,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,iBAAiB,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAE7B,MAAM,QAAQ,CAAC,GAAG,CAAC,qBAAqB,EAAE;YACxC,IAAI,EAAE,EAAE;YACR,SAAS,EAAE,OAAO;SACnB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,sDAAsD;IACxD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.service.test.d.ts","sourceRoot":"","sources":["../../services/telemetry.service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
const { mockRpc, mockReadFile, mockWriteFile, mockMkdir } = vi.hoisted(() => {
|
|
3
|
+
const mockRpc = vi.fn().mockResolvedValue({ error: null });
|
|
4
|
+
const mockReadFile = vi.fn();
|
|
5
|
+
const mockWriteFile = vi.fn().mockResolvedValue(undefined);
|
|
6
|
+
const mockMkdir = vi.fn().mockResolvedValue(undefined);
|
|
7
|
+
return { mockRpc, mockReadFile, mockWriteFile, mockMkdir };
|
|
8
|
+
});
|
|
9
|
+
vi.mock("@supabase/supabase-js", () => ({
|
|
10
|
+
createClient: () => ({ rpc: mockRpc }),
|
|
11
|
+
}));
|
|
12
|
+
vi.mock("fs/promises", () => ({
|
|
13
|
+
default: {
|
|
14
|
+
readFile: mockReadFile,
|
|
15
|
+
writeFile: mockWriteFile,
|
|
16
|
+
mkdir: mockMkdir,
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
import { recordTelemetryPing } from "./telemetry.service.js";
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
vi.clearAllMocks();
|
|
22
|
+
});
|
|
23
|
+
describe("recordTelemetryPing", () => {
|
|
24
|
+
it("creates a new installation ID and calls RPC on first run", async () => {
|
|
25
|
+
mockReadFile.mockRejectedValueOnce(new Error("ENOENT"));
|
|
26
|
+
await recordTelemetryPing();
|
|
27
|
+
expect(mockMkdir).toHaveBeenCalledOnce();
|
|
28
|
+
expect(mockWriteFile).toHaveBeenCalledOnce();
|
|
29
|
+
const writtenId = mockWriteFile.mock.calls[0][1];
|
|
30
|
+
expect(writtenId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
|
|
31
|
+
expect(mockRpc).toHaveBeenCalledWith("upsert_installation", {
|
|
32
|
+
p_id: writtenId,
|
|
33
|
+
p_version: "1.0.10",
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
it("reuses existing installation ID from disk", async () => {
|
|
37
|
+
const existingId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
|
|
38
|
+
mockReadFile.mockResolvedValueOnce(existingId);
|
|
39
|
+
await recordTelemetryPing();
|
|
40
|
+
expect(mockWriteFile).not.toHaveBeenCalled();
|
|
41
|
+
expect(mockRpc).toHaveBeenCalledWith("upsert_installation", {
|
|
42
|
+
p_id: existingId,
|
|
43
|
+
p_version: "1.0.10",
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
it("trims whitespace from stored installation ID", async () => {
|
|
47
|
+
mockReadFile.mockResolvedValueOnce(" aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\n");
|
|
48
|
+
await recordTelemetryPing();
|
|
49
|
+
expect(mockRpc.mock.calls[0][1].p_id).toBe("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
|
|
50
|
+
});
|
|
51
|
+
it("never throws even if Supabase fails", async () => {
|
|
52
|
+
mockReadFile.mockResolvedValueOnce("some-id");
|
|
53
|
+
mockRpc.mockRejectedValueOnce(new Error("network down"));
|
|
54
|
+
await expect(recordTelemetryPing()).resolves.toBeUndefined();
|
|
55
|
+
});
|
|
56
|
+
it("never throws even if filesystem fails entirely", async () => {
|
|
57
|
+
mockReadFile.mockRejectedValueOnce(new Error("ENOENT"));
|
|
58
|
+
mockMkdir.mockRejectedValueOnce(new Error("EPERM"));
|
|
59
|
+
await expect(recordTelemetryPing()).resolves.toBeUndefined();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=telemetry.service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.service.test.js","sourceRoot":"","sources":["../../services/telemetry.service.test.ts"],"names":[],"mappings":"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"}
|