@reinvented/sdk
v0.4.0
Published
Reinvented Platform SDK — error reporting for Reinvented apps
Readme
@reinvented/sdk
Official SDK for building apps on the Reinvented platform. Two entry points — one for server, one for client.
@reinvented/sdk/server ← use in apps/api/
@reinvented/sdk/client ← use in apps/desktop/ and apps/mobile/Installation
pnpm add @reinvented/sdkAlready installed in the app template for all three apps (api, desktop, mobile).
Server SDK (@reinvented/sdk/server)
Use in your API backend (apps/api/). Reads environment variables automatically.
import { createServerSDK, initErrorReporting } from '@reinvented/sdk/server';
const platform = createServerSDK(); // zero-config, reads from env
const app = express();
// ... routes ...
initErrorReporting(app); // DO NOT DELETE — reports errors to platform
app.listen(4000);Environment Variables (auto-read)
| Variable | Required | Description |
|---|---|---|
| PLATFORM_SERVICE_TOKEN | Yes | Per-app authentication token |
| PLATFORM_API_URL | No | API URL (defaults to https://api.reinvented.com) |
Both are automatically injected into every app's environment during provisioning.
Explicit Config (optional)
const platform = createServerSDK({
serviceToken: 'my-token',
platformUrl: 'https://api.reinvented.com',
});Client SDK (@reinvented/sdk/client)
Use in your frontend apps (apps/desktop/, apps/mobile/).
// main.jsx — just importing auto-installs error reporting
import '@reinvented/sdk/client';If you also need to call platform services from the client:
import { createClientSDK } from '@reinvented/sdk/client';
const platform = createClientSDK({
serviceToken: 'your-token', // required — browsers have no env vars
});Services
Both server and client SDKs provide the same three services:
platform.storage — File Storage (Google Cloud Storage)
storage.importFromUrl(url, options?)
Download a file from any URL and store it on the platform CDN.
| Param | Type | Description |
|---|---|---|
| url | string | Source URL to download from |
| options.contentType | string? | Override content type |
| options.extension | string? | Override file extension |
Returns: { url: string, id: string, objectName: string }
const { url } = await platform.storage.importFromUrl('https://example.com/photo.jpg');
// url → 'https://storage.reinvented.cloud/<uuid>/original.jpg'platform.email — Transactional Email (Amazon SES)
email.send({ userId, subject, html?, text? })
Send an email to a platform user. The platform resolves their email address from the user ID.
| Param | Type | Description |
|---|---|---|
| userId | string | Platform user ID (not an email address) |
| subject | string | Email subject line |
| html | string? | HTML email body |
| text | string? | Plain text body (auto-generated from HTML if omitted) |
Returns: { ok: boolean, messageId: string }
Emails are sent from "App Name <[email protected]>".
await platform.email.send({
userId: 'abc-123',
subject: 'Your report is ready',
html: '<h1>Weekly Report</h1><p>Click below to view.</p>',
});platform.ai — AI Tools (Google Gemini)
Default model: gemini-2.5-flash. All inference runs server-side on the platform.
ai.generateJSON({ prompt, schema?, model?, temperature? }) ⭐ Primary
Generate structured JSON from a prompt. This is the most commonly used AI method.
| Param | Type | Default | Description |
|---|---|---|---|
| prompt | string | — | What to generate |
| schema | object? | — | Gemini-format JSON schema |
| model | string? | gemini-2.5-flash | Gemini model ID |
| temperature | number? | 0.7 | 0.0 = deterministic, 1.0 = creative |
Returns: Parsed JSON matching the schema.
Schema types: STRING, NUMBER, INTEGER, BOOLEAN, ARRAY, OBJECT
const product = await platform.ai.generateJSON({
prompt: 'Extract: "Nike Air Max 90, Size 10, $129.99"',
schema: {
type: 'OBJECT',
properties: {
name: { type: 'STRING' },
size: { type: 'STRING' },
price: { type: 'NUMBER' },
},
},
});
// → { name: 'Nike Air Max 90', size: '10', price: 129.99 }ai.generateText({ prompt, model?, temperature?, maxTokens? })
Generate free-form text.
Returns: { text: string }
const { text } = await platform.ai.generateText({
prompt: 'Write a welcome email for a new user named Sarah',
});ai.generateImage({ prompt, aspectRatio? })
Generate an image. Auto-uploaded to platform storage.
Returns: { url: string, id: string, objectName: string }
const { url } = await platform.ai.generateImage({
prompt: 'A minimalist logo for a health tech startup',
aspectRatio: '1:1',
});Error Handling
All SDK methods throw PlatformSDKError on failure:
import { PlatformSDKError } from '@reinvented/sdk/server';
// or: import { PlatformSDKError } from '@reinvented/sdk/client';
try {
await platform.ai.generateJSON({ prompt: '...' });
} catch (err) {
if (err instanceof PlatformSDKError) {
console.error(err.message); // Human-readable error description
console.error(err.code); // Machine-readable error code (see table below)
console.error(err.status); // HTTP status code (0 for network errors)
}
}| Error Code | Meaning | Common Cause |
|---|---|---|
| MISSING_TOKEN | No service token provided | Forgot to set PLATFORM_SERVICE_TOKEN or pass serviceToken |
| NETWORK_ERROR | Can't reach the platform API | Network issue, wrong PLATFORM_API_URL, platform down |
| API_ERROR | Platform returned an error | Bad request data, rate limit, server error (check status and message) |
| INVALID_RESPONSE | Platform returned non-JSON | Platform bug or network corruption |
Error Reporting
The SDK includes automatic error reporting that catches uncaught errors and sends them to the platform for investigation. This is how the platform knows when an app is broken.
How It Works
Server (@reinvented/sdk/server)
Error reporting operates at two levels:
Process-level handlers (automatic on import):
uncaughtException→ logs, reports to platform, exits with code 1unhandledRejection→ logs, reports to platform, continues running
These are installed the moment you
importanything from@reinvented/sdk/server. No setup required. They catch errors that escape Express (startup errors, async code outside request handlers, etc.).Express middleware (requires
initErrorReporting(app)):- Catches errors thrown in Express route handlers and middleware
- Reports each error with the HTTP method and path (e.g.,
POST /graphql) - Calls
next(err)so your own error handler still runs
// MUST be added AFTER all routes and other middleware initErrorReporting(app);
initErrorReporting() reads PLATFORM_API_URL and APP_SLUG from env vars. If the slug is missing, it silently no-ops (safe for local dev without platform env). No auth token is required — the platform API accepts error reports without authentication.
Client (@reinvented/sdk/client)
Error reporting is fully automatic on import. It installs three handlers:
window.error— catches uncaught runtime errors (e.g.,TypeError: Cannot read property 'x' of null)window.unhandledrejection— catches unhandled promise rejectionsconsole.errorinterception — catches framework-swallowed errors (React, Vue, etc. often catch errors and log them viaconsole.errorinstead of letting them propagate)
Errors are sent directly to the platform API via fetch('https://api.reinvented.com/api/app-errors'). The app slug is derived from the URL path. No authentication is required.
The client includes built-in dedup (5 unique errors per session max) to avoid flooding the API during error loops.
This activates on any page — it no longer requires an iframe context.
// main.jsx — just import, error reporting is active immediately
import '@reinvented/sdk/client';What Gets Reported
Every error report includes:
| Field | Description |
|---|---|
| message | Error message (truncated to 500 chars) |
| stack | Stack trace (truncated to 4000 chars) |
| url / context | Where the error occurred (server: HTTP method + path; client: page URL) |
| appSlug | Which app had the error |
Error Reporting Flow
App Error
│
├─ Server ──→ POST /api/app-errors ──→ Platform stores + deduplicates
│ (no auth required)
│
└─ Client ──→ POST /api/app-errors ──→ Platform stores + deduplicates
(no auth required, app slug from URL)Errors are deduplicated by fingerprint (SHA-256 of message + first stack frame). The platform's autonomous bug-fix agent uses MCP tools to triage, investigate, and resolve errors.
Architecture
Your App Platform API Cloud Services
───────── ──────────── ──────────────
platform.storage.import() → POST /sdk/storage/import → Google Cloud Storage
platform.email.send() → POST /sdk/email/send → Amazon SES
platform.ai.generateJSON() → POST /sdk/ai/generate-json → Google Gemini
platform.ai.generateText() → POST /sdk/ai/generate-text → Google Gemini
platform.ai.generateImage()→ POST /sdk/ai/generate-image → Gemini + GCSThe SDK is a thin HTTP client. All heavy lifting happens server-side on the platform API:
- No cloud credentials needed in your app
- No dependencies — zero npm dependencies
- Works everywhere — anywhere
fetchexists
