fix(supabase): remove non-functional SQL introspection, harden storage encoding, add missing endpoints#5371
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Storage gains shared New workflow capabilities: signed upload URLs, update bucket (read-then-PUT merge so unset fields keep current config; block “Keep Current” for visibility), and empty bucket. The Supabase block, registry, and types are wired for these ops; tool versions move to Reviewed by Cursor Bugbot for commit 19fe7f9. Configure here. |
Greptile SummaryThis PR fixes a set of pre-existing bugs in the Supabase tool set and adds three missing Storage endpoints. The old SQL-based introspection (which used a non-existent PostgREST RPC endpoint) is replaced with OpenAPI spec parsing, with limitations (heuristic PK/FK detection, always-empty indexes) clearly documented throughout.
Confidence Score: 5/5Safe to merge — all changed paths are additive or corrective with no backwards-incompatible field removals, and the new tools follow established patterns. The changes are a well-scoped bug-fix and feature addition. The encoding helpers are straightforward and applied consistently. The three new storage tools use the same request/response patterns as existing ones and have proper error guards. The introspect.ts rewrite removes a code path that always failed in production. The only open items are two parameter-type annotations in insert.ts and upsert.ts still marked 'array' despite the PR description claiming they were changed — the runtime body-normalisation code already handles single objects either way, so this is a documentation/annotation gap rather than a runtime failure. No files require special attention for correctness; the minor type-annotation gap in insert.ts and upsert.ts is worth a follow-up but does not block merge. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Block: storage operation] --> B{operation type}
B --> C[storage_create_signed_upload_url]
B --> D[storage_update_bucket]
B --> E[storage_empty_bucket]
B --> F[existing ops: upload / download / list / delete / ...]
C --> C1["encodeStorageSegment(bucket)\nencodeStoragePath(path)"]
C1 --> C2["POST /object/upload/sign/{bucket}/{path}\nx-upsert header if upsert=true"]
C2 --> C3["response.ok? ✓\ndata.url present? ✓\n→ return { signedUrl, path, token }"]
D --> D1["GET /bucket/{bucket}\n(fetch current config)"]
D1 --> D2["merge caller overrides\nwith current values via hasValue()"]
D2 --> D3["PUT /bucket/{bucket}\n(full-replace payload)"]
D3 --> D4["response.ok checked ✓"]
E --> E1["encodeStorageSegment(bucket)"]
E1 --> E2["POST /bucket/{bucket}/empty"]
E2 --> E3["response.ok checked ✓"]
F --> F1["encodeStorageSegment + encodeStoragePath\napplied to all URL-building code"]
F1 --> F2["Supabase Storage API"]
G[introspect tool] --> G1["GET /rest/v1/\nAccept: application/openapi+json\nAccept-Profile: {schema} if provided"]
G1 --> G2["parseOpenApiSpec()\nheuristic PK=id column\nFK=SQL comment pattern"]
G2 --> G3["tables[] with documented caveats"]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Block: storage operation] --> B{operation type}
B --> C[storage_create_signed_upload_url]
B --> D[storage_update_bucket]
B --> E[storage_empty_bucket]
B --> F[existing ops: upload / download / list / delete / ...]
C --> C1["encodeStorageSegment(bucket)\nencodeStoragePath(path)"]
C1 --> C2["POST /object/upload/sign/{bucket}/{path}\nx-upsert header if upsert=true"]
C2 --> C3["response.ok? ✓\ndata.url present? ✓\n→ return { signedUrl, path, token }"]
D --> D1["GET /bucket/{bucket}\n(fetch current config)"]
D1 --> D2["merge caller overrides\nwith current values via hasValue()"]
D2 --> D3["PUT /bucket/{bucket}\n(full-replace payload)"]
D3 --> D4["response.ok checked ✓"]
E --> E1["encodeStorageSegment(bucket)"]
E1 --> E2["POST /bucket/{bucket}/empty"]
E2 --> E3["response.ok checked ✓"]
F --> F1["encodeStorageSegment + encodeStoragePath\napplied to all URL-building code"]
F1 --> F2["Supabase Storage API"]
G[introspect tool] --> G1["GET /rest/v1/\nAccept: application/openapi+json\nAccept-Profile: {schema} if provided"]
G1 --> G2["parseOpenApiSpec()\nheuristic PK=id column\nFK=SQL comment pattern"]
G2 --> G3["tables[] with documented caveats"]
Reviews (5): Last reviewed commit: "fix(supabase): correct download param se..." | Re-trigger Greptile |
|
@cursor review |
|
@cursor review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 9f40427. Configure here.
…torage URL encoding, add missing storage endpoints - introspect.ts no longer attempts raw SQL via a nonexistent PostgREST RPC endpoint (always failed); now uses the OpenAPI-spec path directly with honest heuristic/best-effort documentation for PK/FK/index fields - storage tools now trim + URL-encode bucket/path segments before building request URLs (download, list, get_public_url, create_signed_url, delete_bucket, delete, and the upload API route) - storage_create_signed_url guards against a missing signedURL field in the response instead of silently building a broken URL - add supabase_storage_create_signed_upload_url, supabase_storage_update_bucket, and supabase_storage_empty_bucket tools + block wiring - change insert/upsert `data` param type from 'array' to 'json' to match actual accepted shapes (array or single object) - bump tool versions to semver (1.0 -> 1.0.0) - rewrite a BlockMeta template that implied unsupported Supabase Auth Admin user-provisioning (cherry picked from commit 52b655a)
…d url, and introspect - storage_update_bucket now fetches the bucket's current config first and only overrides isPublic/fileSizeLimit/allowedMimeTypes when the caller explicitly provides them, instead of silently forcing public: false on every update (the Storage API's PUT is a full replace, not a patch) - storage_create_signed_upload_url and storage_empty_bucket now check response.ok before surfacing an error, so a non-2xx response reports Supabase's actual error instead of a misleading parse-side message - introspect.ts drops the spurious ?select=* query param from the OpenAPI spec request (meaningless on the root spec endpoint) (cherry picked from commit 557e407)
…ram coercion, introspect schema header - introspect.ts now sends Accept-Profile when a schema param is given, matching the convention used by the other DB tools, so schema-scoped introspection actually reads from that schema's spec - storage_update_bucket.ts treats an empty-string param the same as "not provided" (e.g. an untouched file size limit input no longer coerces to 0) - the shared "Public Bucket" dropdown always sent an explicit true/false for storage_update_bucket (its default masked "not touched"), which could still flip a public bucket private; added a dedicated "Keep Current / True / False" control for the update operation so omitting a choice genuinely omits the isPublic override (cherry picked from commit c80567b)
…_url Matches the pattern already applied to the new signed-upload-url tool this session — a non-2xx response now surfaces Supabase's actual error message instead of the generic "did not return a signed URL path" one. (cherry picked from commit 9f40427)
9f40427 to
46352f3
Compare
…nd schema hint mismatch
Found by a second, per-tool parallel validation pass against live Supabase/PostgREST docs and source:
- storage_get_public_url.ts and storage_create_signed_url.ts sent
download=true literally, which Supabase's Storage API treats as a
filename override (renaming the downloaded file to "true") rather
than a boolean flag; forcing a download while keeping the original
filename requires an empty download= value
- storage_create_signed_url.ts also sent download in the POST body,
which the sign endpoint ignores entirely — forcing download only
works as a query param on the returned URL
- storage_create_signed_upload_url.ts read a `path` field from the API
response that doesn't exist there; it now echoes the caller-supplied
path, matching the official storage-js client
- introspect.ts's nullable heuristic didn't disclose that a NOT NULL
column with a default is misreported as nullable (PostgREST omits it
from the OpenAPI required list in that case); documented alongside
the other already-disclosed heuristics, and removed a tautological
schema-filter check left over from an earlier revision
- insert.ts/upsert.ts's `data` param reverted from 'json' back to
'array': the 'json' type mapped to an LLM-facing JSON-schema type of
'object', which contradicted the param's own description ("array of
objects or a single object")
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 19fe7f9. Configure here.
Summary
dataparam type fromarraytojsonto match what's actually accepted (array or single object)1.0->1.0.0)Type of Change
Testing
Ran
tsc --noEmit(clean),biome check(clean), existing supabase unit tests pass. Cross-checked every tool against PostgREST/Supabase Storage API docs and storage-js source via 3 independent parallel review passes (DB/RPC tools, storage tools, block wiring) — all fully aligned, no backwards-incompatible field removals.Checklist