@intrface/solidparty-sdk
v0.0.1
Published
A tiny TypeScript client for talking to **Solidparty** (our Copyparty + S3 storage gateway) from **Convex backends** and other TypeScript servers.
Downloads
95
Readme
@intrface/solidparty-sdk
A tiny TypeScript client for talking to Solidparty (our Copyparty + S3 storage gateway) from Convex backends and other TypeScript servers.
- ✅ Safe for server-side use (Convex actions / server routes)
- ✅ No browser secrets (admin credentials never leave the backend)
- ✅ Simple, file-oriented API:
upload,delete,list
IMPORTANT: Do not import this SDK in client/browser code. Use it only from Convex
action/internalAction/ server-side contexts.
Installation
From your monorepo root (homebase):
pnpm install
pnpm --filter @intrface/solidparty-sdk buildTo publish to your private npm registry, bump the version in package.json and run your existing npm publish workflow for scoped packages.
Configuration
Solidparty is configured via environment variables on the Solidparty container. For Convex, you will set matching env vars so the SDK can connect to that instance.
Suggested Convex environment variables:
SOLIDPARTY_BASE_URL– e.g.https://solidparty.intrface.dev/publicor internal service DNSSOLIDPARTY_ADMIN_USER– admin username configured inentrypoint.shSOLIDPARTY_ADMIN_PASSWORD– admin password (never exposed to client)
Usage with Convex
1. Create a helper module in your Convex project
// convex/solidparty.ts
import { createSolidpartyClient } from "@intrface/solidparty-sdk";
export function solidparty() {
const baseUrl = process.env.SOLIDPARTY_BASE_URL;
const username = process.env.SOLIDPARTY_ADMIN_USER;
const password = process.env.SOLIDPARTY_ADMIN_PASSWORD;
if (!baseUrl || !username || !password) {
throw new Error("Missing Solidparty env vars in Convex environment");
}
return createSolidpartyClient({
baseUrl,
username,
password,
// Convex exposes a global fetch implementation
fetchImpl: fetch,
});
}2. Use from an internal Convex action
// convex/files.ts
import { internalAction } from "convex/server";
import { v } from "convex/values";
import { solidparty } from "./solidparty";
export const uploadReport = internalAction({
args: {
fileId: v.string(),
// Raw bytes from previous pipeline step (e.g. generated PDF)
bytes: v.bytes(),
contentType: v.optional(v.string()),
},
handler: async (ctx, args) => {
const client = solidparty();
const { url, path } = await client.upload({
path: `reports/${args.fileId}.pdf`,
body: new Uint8Array(args.bytes),
contentType: args.contentType ?? "application/pdf",
});
// Store URL in Convex DB so frontends can access it
await ctx.db.patch(args.fileId, {
reportUrl: url,
reportPath: path,
});
},
});3. Deleting an object
export const deleteReport = internalAction({
args: { path: v.string() },
handler: async (_ctx, args) => {
const client = solidparty();
await client.delete(args.path); // e.g. "reports/abc123.pdf"
},
});4. Listing a directory
export const listPublicImages = internalAction({
args: {},
handler: async () => {
const client = solidparty();
return client.list({ prefix: "images" });
},
});Data Safety & Backups
Solidparty itself is stateless: it forwards reads/writes to your S3-compatible bucket. For durability and backup:
- Enable S3 Versioning on the bucket used by Solidparty.
- Optionally configure Cross-Region Replication to a second bucket.
- Add Lifecycle Rules to move old versions to Glacier/Deep Archive for long-term storage.
Your Convex apps should treat Solidparty URLs as authoritative references, while relying on S3 for actual durability and recovery.
API Reference
createSolidpartyClient(config)
createSolidpartyClient({
baseUrl: string; // e.g. "https://solidparty.service/public"
username: string; // Solidparty admin username
password: string; // Solidparty admin password
fetchImpl?: typeof fetch; // Optional, defaults to globalThis.fetch
});client.upload(params)
await client.upload({
path: string; // "images/avatar-123.png"
body: ArrayBuffer | Uint8Array;
contentType?: string; // e.g. "image/png"
});Returns:
{
url: string; // Full URL to the stored object
path: string; // Normalized storage path
etag?: string; // Optional ETag from upstream storage
}client.delete(path)
Deletes the object at the given path. 404s are treated as success.
client.list({ prefix? })
Lists objects under a directory prefix. Requires Solidparty directory listing (JSON mode) to be enabled for the volume.
const items = await client.list({ prefix: "images" });
// items: { name, path, size, lastModified, url }[]You can now point any Convex backend at Solidparty and have a consistent, documented storage connector without rebuilding the integration each time.
