Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions convex/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,9 @@ export const getMachineStats = query({

const errorNames = await ctx.db
.query("events")
.withIndex("by_machine_time", (q) => q.eq("machineId", machineId))
.filter((q) => q.eq(q.field("type"), "error"))
.withIndex("by_machine_type_time", (q) =>
q.eq("machineId", machineId).eq("type", "error")
)
.collect();
const topErrors = Array.from(
errorNames.reduce((map, e) => map.set(e.name, (map.get(e.name) ?? 0) + 1), new Map<string, number>())
Expand All @@ -249,8 +250,9 @@ export const getMachineStats = query({

const pageviews = await ctx.db
.query("events")
.withIndex("by_machine_time", (q) => q.eq("machineId", machineId))
.filter((q) => q.eq(q.field("type"), "pageview"))
.withIndex("by_machine_type_time", (q) =>
q.eq("machineId", machineId).eq("type", "pageview")
)
.collect();
const topPages = Array.from(
pageviews.reduce((map, e) => map.set(e.url, (map.get(e.url) ?? 0) + 1), new Map<string, number>())
Expand Down
9 changes: 8 additions & 1 deletion convex/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ http.route({
method: "POST",
handler: httpAction(async (ctx, request) => {
if (!isAuthorized(request)) {
return new Response("Unauthorized", { status: 401 });
return new Response("Unauthorized", {
status: 401,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, x-wisp-token",
Comment on lines +22 to +24

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant CORS response headers on the 401 reply

Access-Control-Allow-Methods and Access-Control-Allow-Headers are only inspected by browsers on preflight (OPTIONS) responses; they have no effect on the actual POST 401 reply. Only Access-Control-Allow-Origin is needed here to let the browser read the response body. The extra headers are harmless, but they're dead weight on every unauthorized request.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

},
});
}

const body = await request.json() as { events: unknown[] };
Expand Down
1 change: 1 addition & 0 deletions convex/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default defineSchema({
.index("by_session", ["sessionId"])
.index("by_type_time", ["type", "timestamp"])
.index("by_machine_time", ["machineId", "timestamp"])
.index("by_machine_type_time", ["machineId", "type", "timestamp"])
.searchIndex("search_name", { searchField: "name", filterFields: ["type"] }),

dailyStats: defineTable({
Expand Down
9 changes: 7 additions & 2 deletions src/providers/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [loading, setLoading] = useState(true);

useEffect(() => {
// Bind Supabase auth state to Wisp analytics identity
const unsubscribeWisp = bindSupabase(supabase);
// Bind Supabase auth state to Wisp analytics identity (no-op if wisp not initialized)
let unsubscribeWisp = () => {};
try {
unsubscribeWisp = bindSupabase(supabase);
} catch {
// wisp not initialized — skip analytics identity binding
Comment on lines +17 to +18

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Silent catch masks real bindSupabase errors

The empty catch block swallows any error thrown by bindSupabase, not just the "wisp not initialized" case. If the library is initialized but throws for a different reason (e.g., incompatible Supabase client version, internal assertion), the failure would disappear silently with no way to diagnose it. At minimum, logging the caught error as a warning preserves observability without breaking the fallback behaviour.

}

// Set up auth state listener FIRST
const {
Expand Down
Loading