adsmurai-proxy-sdk
v1.1.1
Published
Lightweight SDK for Adsmurai Supabase proxy edge functions
Readme
adsmurai-proxy-sdk
Lightweight TypeScript SDK for Adsmurai's Supabase proxy edge functions. Provides a unified client to talk to any proxy edge function through a declarative proxy definition system with URL patterns, whitelist validation, and support for both proxy and direct modes.
Install
npm install adsmurai-proxy-sdkQuick start
1. Define your proxy
import { defineProxy } from "adsmurai-proxy-sdk";
export const feedsProxy = defineProxy({
functionName: "feeds-proxy",
url: {
baseUrl: "https://feeds.adsmurai.com",
type: "org-scoped",
orgTemplate: "{baseUrl}/api/v2/organization/{orgId}/{path}",
},
whitelist: {
org: { GET: ["data-imports", "optimized-feeds", "channels"] },
},
});2a. Vanilla TypeScript
import { SmartClient } from "adsmurai-proxy-sdk";
const client = new SmartClient({
definition: feedsProxy,
proxyConfig: {
supabaseUrl: "https://xyz.supabase.co",
supabaseAnonKey: "eyJhbGci...",
},
mode: "proxy",
});
const products = await client.get<Product[]>("data-imports", {
token: accessToken,
orgId: "42",
queryParams: { limit: 20 },
});2b. React
import { ProxySdkProvider, useProxyClient } from "adsmurai-proxy-sdk/react";
// 1. Wrap your app with the provider
function App() {
return (
<ProxySdkProvider
proxies={{
"feeds-proxy": {
definition: feedsProxy,
supabaseUrl: import.meta.env.VITE_SUPABASE_URL,
supabaseAnonKey: import.meta.env.VITE_SUPABASE_ANON_KEY,
},
}}
getToken={() => getCookie("amp_access_token")}
orgId={currentOrgId}
>
<Dashboard />
</ProxySdkProvider>
);
}
// 2. Use the hook in any child component
function ProductList() {
const { get } = useProxyClient("feeds-proxy");
useEffect(() => {
get<Product[]>("data-imports", { limit: 20 }).then(setProducts);
}, [get]);
}2c. React Query
import { useProxyQuery, useProxyMutation, proxyQueryKey } from "adsmurai-proxy-sdk/react-query";
function DataImports() {
const { data, isLoading } = useProxyQuery<DataImport[]>(
"feeds-proxy",
"data-imports",
{ queryParams: { limit: 20 } },
);
const { mutate } = useProxyMutation<Product, CreateProductInput>(
"feeds-proxy",
"data-imports",
{ method: "POST" },
);
// Invalidate queries
queryClient.invalidateQueries({
queryKey: proxyQueryKey("feeds-proxy", "data-imports"),
});
}API
Core (adsmurai-proxy-sdk)
| Export | Description |
|--------|-------------|
| SmartClient | Unified HTTP client — validates against whitelist, builds upstream URLs, routes through generic-proxy or directly |
| createSmartProxy(options) | Factory function for SmartClient |
| defineProxy(definition) | Type-safe factory for creating ProxyDefinition objects |
| validateRequest(definition, method, path) | Validate a request against the proxy's whitelist |
| buildUpstreamUrl(definition, path, scope, orgId?, queryParams?) | Build the full upstream URL from a proxy definition |
| resolveScope(definition, method, path) | Determine if a path is org-scoped or global |
| ProxyError | Error with .status, .code, and optional .requestId |
| ProxyDefinition | Type: declarative proxy config with URL patterns and whitelist |
| ProxyConfig | Type: { supabaseUrl, supabaseAnonKey, directUrl? } |
React (adsmurai-proxy-sdk/react)
| Export | Description |
|--------|-------------|
| ProxySdkProvider | Context provider — configures proxies, getToken, optional orgId, useDirectUrls, and protocol |
| useProxyClient(functionName) | Hook returning { get, post, put, patch, delete, request } — token and orgId auto-injected |
| ProxyEntry | Type: proxy definition + Supabase config for a single proxy |
React Query (adsmurai-proxy-sdk/react-query)
| Export | Description |
|--------|-------------|
| useProxyQuery(proxyName, path, options?) | React Query hook for GET requests through a proxy |
| useProxyMutation(proxyName, path, options?) | React Query mutation hook for non-GET requests |
| proxyQueryKey(proxyName, path?, queryParams?) | Helper to build query keys for invalidation |
How it works
Proxy mode (default)
Your app
→ useProxyClient("feeds-proxy") or new SmartClient(...)
1. Validate path against whitelist (fail-fast)
2. Build upstream URL from ProxyDefinition
3. POST {supabaseUrl}/functions/v1/generic-proxy
Body: { targetUrl: "https://feeds.../api/v2/...", method: "GET" }
Headers: Authorization: Bearer <token>, apikey: <anonKey>
→ generic-proxy edge function forwards to upstream APIDirect mode
When useDirectUrls is true, requests go directly to the upstream API using session cookies (credentials: "include"), bypassing the proxy entirely.
URL patterns
The UrlPattern type supports four strategies:
| Type | Description |
|------|-------------|
| simple | {baseUrl}/{path} — no org scoping |
| org-scoped | Uses orgTemplate for all paths (orgId required) |
| conditional | Checks org whitelist first, then global — allows mixed paths |
| custom | Full control via buildUrl function |
Adding a new proxy
Define a new ProxyDefinition and pass it to the provider or SmartClient:
const analyticsProxy = defineProxy({
functionName: "analytics-proxy",
url: {
baseUrl: "https://analytics.adsmurai.com",
type: "org-scoped",
orgTemplate: "{baseUrl}/api/v1/org/{orgId}/{path}",
},
whitelist: {
org: { GET: ["reports", "dashboards"] },
},
});Development
npm run build # Build with tsup (ESM + CJS + types)
npm run typecheck # Type-check without emitting