mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-05 05:05:08 +02:00
feat: wire Supabase credentials and expose tables via Data API
Add supabase/config.sh with project URL and publishable key (safe to commit — RLS restricts to INSERT only). Update telemetry-sync, community-dashboard, and update-check to source the config and include proper auth headers for the Supabase REST API. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,10 @@ set -uo pipefail
|
||||
|
||||
GSTACK_DIR="${GSTACK_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
|
||||
|
||||
# Supabase connection — will be populated once project is created
|
||||
# Source Supabase config if not overridden by env
|
||||
if [ -z "${GSTACK_SUPABASE_URL:-}" ] && [ -f "$GSTACK_DIR/supabase/config.sh" ]; then
|
||||
. "$GSTACK_DIR/supabase/config.sh"
|
||||
fi
|
||||
SUPABASE_URL="${GSTACK_SUPABASE_URL:-}"
|
||||
ANON_KEY="${GSTACK_SUPABASE_ANON_KEY:-}"
|
||||
|
||||
|
||||
@@ -18,8 +18,12 @@ CURSOR_FILE="$ANALYTICS_DIR/.last-sync-line"
|
||||
RATE_FILE="$ANALYTICS_DIR/.last-sync-time"
|
||||
CONFIG_CMD="$GSTACK_DIR/bin/gstack-config"
|
||||
|
||||
# Default endpoint — will be updated once Supabase project is created
|
||||
# Source Supabase config if not overridden by env
|
||||
if [ -z "${GSTACK_TELEMETRY_ENDPOINT:-}" ] && [ -f "$GSTACK_DIR/supabase/config.sh" ]; then
|
||||
. "$GSTACK_DIR/supabase/config.sh"
|
||||
fi
|
||||
ENDPOINT="${GSTACK_TELEMETRY_ENDPOINT:-}"
|
||||
ANON_KEY="${GSTACK_SUPABASE_ANON_KEY:-}"
|
||||
|
||||
# ─── Pre-checks ──────────────────────────────────────────────
|
||||
# No endpoint configured yet → exit silently
|
||||
@@ -98,8 +102,11 @@ BATCH="$BATCH]"
|
||||
|
||||
# ─── POST to Supabase ────────────────────────────────────────
|
||||
RESPONSE="$(curl -sf --max-time 10 \
|
||||
-X POST "$ENDPOINT" \
|
||||
-X POST "${ENDPOINT}/telemetry_events" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "apikey: ${ANON_KEY}" \
|
||||
-H "Authorization: Bearer ${ANON_KEY}" \
|
||||
-H "Prefer: return=minimal" \
|
||||
-d "$BATCH" 2>/dev/null || true)"
|
||||
|
||||
# ─── Update cursor on success ────────────────────────────────
|
||||
|
||||
+11
-3
@@ -143,13 +143,21 @@ mkdir -p "$STATE_DIR"
|
||||
# Fire Supabase install ping in background (parallel, non-blocking)
|
||||
# This logs an update check event for community health metrics.
|
||||
# If the endpoint isn't configured or Supabase is down, this is a no-op.
|
||||
# Source Supabase config for install ping
|
||||
if [ -z "${GSTACK_TELEMETRY_ENDPOINT:-}" ] && [ -f "$GSTACK_DIR/supabase/config.sh" ]; then
|
||||
. "$GSTACK_DIR/supabase/config.sh"
|
||||
fi
|
||||
_SUPA_ENDPOINT="${GSTACK_TELEMETRY_ENDPOINT:-}"
|
||||
if [ -n "$_SUPA_ENDPOINT" ]; then
|
||||
_SUPA_KEY="${GSTACK_SUPABASE_ANON_KEY:-}"
|
||||
if [ -n "$_SUPA_ENDPOINT" ] && [ -n "$_SUPA_KEY" ]; then
|
||||
_OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||
curl -sf --max-time 5 \
|
||||
-X POST "${_SUPA_ENDPOINT%/telemetry-ingest}/update-check" \
|
||||
-X POST "${_SUPA_ENDPOINT}/update_checks" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"version\":\"$LOCAL\",\"os\":\"$_OS\"}" \
|
||||
-H "apikey: ${_SUPA_KEY}" \
|
||||
-H "Authorization: Bearer ${_SUPA_KEY}" \
|
||||
-H "Prefer: return=minimal" \
|
||||
-d "{\"gstack_version\":\"$LOCAL\",\"os\":\"$_OS\"}" \
|
||||
>/dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# Supabase project config for gstack telemetry
|
||||
# These are PUBLIC keys — safe to commit (like Firebase public config).
|
||||
# RLS policies restrict what the anon/publishable key can do (INSERT only).
|
||||
|
||||
GSTACK_SUPABASE_URL="https://frugpmstpnojnhfyimgv.supabase.co"
|
||||
GSTACK_SUPABASE_ANON_KEY="sb_publishable_tR4i6cyMIrYTE3s6OyHGHw_ppx2p6WK"
|
||||
|
||||
# Telemetry ingest endpoint (Data API)
|
||||
GSTACK_TELEMETRY_ENDPOINT="${GSTACK_SUPABASE_URL}/rest/v1"
|
||||
+15
-2
@@ -257,9 +257,22 @@ describe('gstack-telemetry-sync', () => {
|
||||
});
|
||||
|
||||
describe('gstack-community-dashboard', () => {
|
||||
test('shows unconfigured message when no Supabase URL', () => {
|
||||
const output = run(`${BIN}/gstack-community-dashboard`);
|
||||
test('shows unconfigured message when no Supabase config available', () => {
|
||||
// Use a fake GSTACK_DIR with no supabase/config.sh
|
||||
const output = run(`${BIN}/gstack-community-dashboard`, {
|
||||
GSTACK_DIR: tmpDir,
|
||||
GSTACK_SUPABASE_URL: '',
|
||||
GSTACK_SUPABASE_ANON_KEY: '',
|
||||
});
|
||||
expect(output).toContain('Supabase not configured');
|
||||
expect(output).toContain('gstack-analytics');
|
||||
});
|
||||
|
||||
test('connects to Supabase when config exists', () => {
|
||||
// Use the real GSTACK_DIR which has supabase/config.sh
|
||||
const output = run(`${BIN}/gstack-community-dashboard`);
|
||||
expect(output).toContain('gstack community dashboard');
|
||||
// Should not show "not configured" since config.sh exists
|
||||
expect(output).not.toContain('Supabase not configured');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user