feat: integrate supabase into the backend#148
Conversation
WalkthroughIntroduces Supabase integration: adds SDK dependency, configures a reusable client, adds environment variables, documents usage, and provides a validation script that queries a test table. Changes
Sequence Diagram(s)sequenceDiagram
actor Dev
participant ValidateScript as scripts/validate-supabase.ts
participant SupabaseClient as src/config/supabase.ts
participant SupabaseAPI as Supabase Service
Dev->>ValidateScript: run script
ValidateScript->>SupabaseClient: import supabase
ValidateScript->>SupabaseAPI: from('test').select('*')
SupabaseAPI-->>ValidateScript: data or error
ValidateScript-->>Dev: log data or throw error
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changesNone found. All changes align with Supabase integration objectives. Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
.env.example (1)
54-56: Reorder keys and add trailing newline to satisfy dotenv-linter; consider documenting service role key.
- dotenv-linter warns about ordering and missing final newline.
- Suggested minimal change:
-# Supabase -SUPABASE_URL=https://your-project.supabase.co -SUPABASE_ANON_KEY=your-anon-key +# Supabase +SUPABASE_ANON_KEY=your-anon-key +SUPABASE_URL=https://your-project.supabase.co +
- Optional: For backend-only operations requiring RLS bypass, you may also document (commented) SUPABASE_SERVICE_ROLE_KEY, but ensure it’s never committed.
readme.md (1)
239-251: Add usage instructions for the validation script and note ESM/CJS requirement.
- Include how to run the validator:
npm run validate:supabase # or ts-node scripts/validate-supabase.ts
- If you keep CommonJS, the validator may fail due to Supabase ESM. Document either the ESM migration or use of dynamic import in the config.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (5)
.env.example(1 hunks)package.json(1 hunks)readme.md(1 hunks)scripts/validate-supabase.ts(1 hunks)src/config/supabase.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
scripts/validate-supabase.ts (2)
src/config/supabase.ts (1)
supabase(6-6)src/utils/logger.ts (1)
error(29-31)
src/config/supabase.ts (1)
global.d.ts (1)
createClient(3-3)
🪛 dotenv-linter (3.3.0)
.env.example
[warning] 56-56: [EndingBlankLine] No blank line at the end of the file
[warning] 56-56: [UnorderedKey] The SUPABASE_ANON_KEY key should go before the SUPABASE_URL key
| "@aws-sdk/s3-request-presigner": "^3.798.0", | ||
| "@prisma/client": "^6.4.1", | ||
| "@stellar/stellar-sdk": "^13.3.0", | ||
| "@supabase/supabase-js": "^2.54.0", |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Critical: @supabase/supabase-js v2 is ESM-only; repo is CommonJS.
With "type": "commonjs" and typical TS config compiling to CJS, importing v2 will throw ERR_REQUIRE_ESM at runtime. Choose one:
- Migrate the project to ESM (recommended): set "type": "module", compile TS to ESNext, and run with tsx or node --loader ts-node/esm.
- Or keep CJS and use dynamic import for Supabase (wrap createClient in an async factory and await import('@supabase/supabase-js')).
Also consider adding a script to run the validator (see comment on scripts/validate-supabase.ts).
🏁 Script executed:
#!/bin/bash
# Verify current module system and likely mismatch
echo "package.json type:"; jq -r '.type' package.json 2>/dev/null || true
echo; echo "tsconfig module target(s):"
fd -a tsconfig.json | xargs -I{} sh -c 'echo "-> {}"; cat "{}" | rg -n "\"module\"\\s*:\\s*\"[^\"]+\"" || true'Length of output: 381
Critical: ESM‐only @supabase/supabase-js v2 in a CommonJS project
We’ve verified your setup:
- package.json has no
"type"field (defaults to CommonJS) - tsconfig.json’s
"module"is set to"CommonJS"
Since v2 of @supabase/supabase-js ships as ESM-only, requiring it in a CJS environment will throw ERR_REQUIRE_ESM at runtime. Please choose one of the following resolutions:
• Migrate the project to ESM (recommended)
– Add "type": "module" to package.json
– Update tsconfig.json’s "module" to an ESNext target
– Run with an ESM-aware loader (e.g. tsx or node --loader ts-node/esm)
• Stay on CommonJS but load Supabase dynamically
– Change your client factory to an async function:
js export async function createSupabaseClient() { const { createClient } = await import('@supabase/supabase-js'); return createClient(/* … */); }
Additionally, consider adding a validation script to your CI pipeline (see scripts/validate-supabase.ts) to catch ESM/CJS mismatches early.
🤖 Prompt for AI Agents
In package.json around line 29, you're importing "@supabase/supabase-js" v2 in a
CommonJS project which will throw ERR_REQUIRE_ESM; fix by either migrating the
project to ESM or loading Supabase dynamically: to migrate, add "type":"module"
to package.json, update tsconfig.json "module" to an ES module target (e.g.
ESNext), and run with an ESM-aware runner (tsx or node with an ESM loader); to
remain CommonJS, refactor the Supabase client factory into an async function
that uses dynamic import() to load '@supabase/supabase-js' and return
createClient, and update call sites to await it; additionally add a CI
validation script to catch ESM/CJS mismatches early.
| import { supabase } from '../src/config/supabase'; | ||
|
|
||
| async function test() { | ||
| const { data, error } = await supabase.from('test').select('*'); | ||
| if (error) throw error; | ||
| console.log(data); | ||
| } | ||
|
|
||
| test(); No newline at end of file |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Harden the validator: limit result size, add error handling and exit codes; allow table override.
Prevents large reads, returns proper non-zero exit on failure, and lets users specify a table.
-import { supabase } from '../src/config/supabase';
-
-async function test() {
- const { data, error } = await supabase.from('test').select('*');
- if (error) throw error;
- console.log(data);
-}
-
-test();
+import { supabase } from '../src/config/supabase';
+
+async function main() {
+ const table = process.env.SUPABASE_TEST_TABLE || 'test';
+ const { data, error } = await supabase.from(table).select('*').limit(1);
+ if (error) {
+ console.error('Supabase validation failed:', error);
+ process.exit(1);
+ }
+ console.log('Supabase connectivity OK. Sample:', data);
+}
+
+main().catch((e) => {
+ console.error('Unexpected error running Supabase validator:', e);
+ process.exit(1);
+});Optional: add a package.json script "validate:supabase": "ts-node scripts/validate-supabase.ts".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { supabase } from '../src/config/supabase'; | |
| async function test() { | |
| const { data, error } = await supabase.from('test').select('*'); | |
| if (error) throw error; | |
| console.log(data); | |
| } | |
| test(); | |
| import { supabase } from '../src/config/supabase'; | |
| async function main() { | |
| const table = process.env.SUPABASE_TEST_TABLE || 'test'; | |
| const { data, error } = await supabase.from(table).select('*').limit(1); | |
| if (error) { | |
| console.error('Supabase validation failed:', error); | |
| process.exit(1); | |
| } | |
| console.log('Supabase connectivity OK. Sample:', data); | |
| } | |
| main().catch((e) => { | |
| console.error('Unexpected error running Supabase validator:', e); | |
| process.exit(1); | |
| }); |
| import { createClient } from '@supabase/supabase-js'; | ||
|
|
||
| const supabaseUrl = process.env.SUPABASE_URL!; | ||
| const supabaseKey = process.env.SUPABASE_ANON_KEY!; | ||
|
|
||
| export const supabase = createClient(supabaseUrl, supabaseKey); No newline at end of file |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Validate env vars and configure server-safe auth options; avoid non-null assertions.
Fail fast with clear errors and set server-side auth options to avoid persisting sessions. Example:
-import { createClient } from '@supabase/supabase-js';
-
-const supabaseUrl = process.env.SUPABASE_URL!;
-const supabaseKey = process.env.SUPABASE_ANON_KEY!;
-
-export const supabase = createClient(supabaseUrl, supabaseKey);
+import { createClient } from '@supabase/supabase-js';
+
+const supabaseUrl = process.env.SUPABASE_URL;
+const supabaseKey = process.env.SUPABASE_ANON_KEY;
+
+if (!supabaseUrl) {
+ throw new Error('Missing SUPABASE_URL. Set it in your environment.');
+}
+if (!supabaseKey) {
+ throw new Error('Missing SUPABASE_ANON_KEY. Set it in your environment.');
+}
+
+export const supabase = createClient(supabaseUrl, supabaseKey, {
+ auth: {
+ persistSession: false,
+ autoRefreshToken: false,
+ },
+});Note: If you remain on CommonJS, importing v2 ESM will still fail; see package.json comment for options.
To ensure envs are loaded before this module, confirm where dotenv is initialized (e.g., app bootstrap) or import 'dotenv/config' in the entrypoint.
🏁 Script executed:
#!/bin/bash
# Where is dotenv configured?
rg -n "dotenv\\.config\\(|from 'dotenv/config'|from \"dotenv/config\"" -A1Length of output: 694
Validate SUPABASE env vars and configure server-side auth
We need to remove non-null assertions, fail fast with clear errors, and opt out of client-side session persistence. Also, ensure your env is loaded before initializing the client (this file currently doesn’t call dotenv.config(), whereas other config files do).
- Replace
process.env.SUPABASE_URL!/SUPABASE_ANON_KEY!with guarded access and throw if missing - Pass
{ auth: { persistSession: false, autoRefreshToken: false } }tocreateClient - Either import
'dotenv/config'at the top or confirm your bootstrap loadsdotenv.config()before this module runs
Suggested diff:
-import { createClient } from '@supabase/supabase-js';
-
-const supabaseUrl = process.env.SUPABASE_URL!;
-const supabaseKey = process.env.SUPABASE_ANON_KEY!;
-
-export const supabase = createClient(supabaseUrl, supabaseKey);
+import 'dotenv/config';
+import { createClient } from '@supabase/supabase-js';
+
+const supabaseUrl = process.env.SUPABASE_URL;
+const supabaseKey = process.env.SUPABASE_ANON_KEY;
+
+if (!supabaseUrl) {
+ throw new Error('Missing SUPABASE_URL. Set it in your environment.');
+}
+if (!supabaseKey) {
+ throw new Error('Missing SUPABASE_ANON_KEY. Set it in your environment.');
+}
+
+export const supabase = createClient(supabaseUrl, supabaseKey, {
+ auth: {
+ persistSession: false,
+ autoRefreshToken: false,
+ },
+});Tagging as requiring changes so the client initialization is both safe and predictable.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { createClient } from '@supabase/supabase-js'; | |
| const supabaseUrl = process.env.SUPABASE_URL!; | |
| const supabaseKey = process.env.SUPABASE_ANON_KEY!; | |
| export const supabase = createClient(supabaseUrl, supabaseKey); | |
| import 'dotenv/config'; | |
| import { createClient } from '@supabase/supabase-js'; | |
| const supabaseUrl = process.env.SUPABASE_URL; | |
| const supabaseKey = process.env.SUPABASE_ANON_KEY; | |
| if (!supabaseUrl) { | |
| throw new Error('Missing SUPABASE_URL. Set it in your environment.'); | |
| } | |
| if (!supabaseKey) { | |
| throw new Error('Missing SUPABASE_ANON_KEY. Set it in your environment.'); | |
| } | |
| export const supabase = createClient(supabaseUrl, supabaseKey, { | |
| auth: { | |
| persistSession: false, | |
| autoRefreshToken: false, | |
| }, | |
| }); |
🤖 Prompt for AI Agents
In src/config/supabase.ts lines 1-6, remove the non-null assertions and instead
read SUPABASE_URL and SUPABASE_ANON_KEY from process.env with guarded checks
that throw clear, fast-fail errors if either is missing; ensure the module loads
environment variables (import 'dotenv/config' at the top unless your bootstrap
guarantees dotenv.config() runs before this file is imported); and initialize
createClient with server-side auth options by passing { auth: { persistSession:
false, autoRefreshToken: false } } as the third argument so sessions are not
persisted client-side.
🚀 Volunchain Pull Request
Mark with an
xall the checkboxes that apply (like[x])📌 Type of Change
📝 Changes description
Implemented Supabase in the backend and a test script
⏰ Time spent breakdown
10 minutes
🌌 Comments
Feedback about anything is appreciated.
Thank you for contributing to Volunchain, we are glad that you have chosen us as your project of choice and we hope that you continue to contribute to this great project, so that together we can make our mark at the top!
Summary by CodeRabbit
New Features
Documentation
Chores