@rebasepro/agent-skills 0.0.1-canary.4829d6e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/package.json +21 -0
  4. package/skills/rebase-admin/SKILL.md +816 -0
  5. package/skills/rebase-api/SKILL.md +673 -0
  6. package/skills/rebase-api/references/.gitkeep +3 -0
  7. package/skills/rebase-auth/SKILL.md +1323 -0
  8. package/skills/rebase-auth/references/.gitkeep +3 -0
  9. package/skills/rebase-backend-postgres/SKILL.md +633 -0
  10. package/skills/rebase-backend-postgres/references/.gitkeep +3 -0
  11. package/skills/rebase-basics/SKILL.md +757 -0
  12. package/skills/rebase-basics/references/.gitkeep +3 -0
  13. package/skills/rebase-collections/SKILL.md +1421 -0
  14. package/skills/rebase-collections/references/.gitkeep +3 -0
  15. package/skills/rebase-cron-jobs/SKILL.md +704 -0
  16. package/skills/rebase-cron-jobs/references/.gitkeep +1 -0
  17. package/skills/rebase-custom-functions/SKILL.md +281 -0
  18. package/skills/rebase-deployment/SKILL.md +894 -0
  19. package/skills/rebase-deployment/references/.gitkeep +3 -0
  20. package/skills/rebase-design-language/SKILL.md +692 -0
  21. package/skills/rebase-email/SKILL.md +701 -0
  22. package/skills/rebase-email/references/.gitkeep +1 -0
  23. package/skills/rebase-entity-history/SKILL.md +485 -0
  24. package/skills/rebase-entity-history/references/.gitkeep +1 -0
  25. package/skills/rebase-local-env-setup/SKILL.md +189 -0
  26. package/skills/rebase-local-env-setup/references/.gitkeep +3 -0
  27. package/skills/rebase-realtime/SKILL.md +759 -0
  28. package/skills/rebase-realtime/references/.gitkeep +3 -0
  29. package/skills/rebase-sdk/SKILL.md +617 -0
  30. package/skills/rebase-sdk/references/.gitkeep +0 -0
  31. package/skills/rebase-security/SKILL.md +646 -0
  32. package/skills/rebase-storage/SKILL.md +989 -0
  33. package/skills/rebase-storage/references/.gitkeep +3 -0
  34. package/skills/rebase-studio/SKILL.md +772 -0
  35. package/skills/rebase-studio/references/.gitkeep +3 -0
  36. package/skills/rebase-ui-components/SKILL.md +1579 -0
  37. package/skills/rebase-ui-components/references/.gitkeep +3 -0
  38. package/skills/rebase-webhooks/SKILL.md +618 -0
  39. package/skills/rebase-webhooks/references/.gitkeep +1 -0
@@ -0,0 +1,281 @@
1
+ ---
2
+ name: rebase-custom-functions
3
+ description: Guide for adding custom API endpoints to a Rebase backend using the file-based function discovery pattern. Use this skill when the user needs a custom endpoint, webhook handler, payment callback, PDF generator, or any server-side route beyond auto-generated CRUD.
4
+ ---
5
+
6
+ # Custom API Functions
7
+
8
+ > **IMPORTANT FOR AGENTS**: Rebase supports **auto-discovered custom Hono routes** via the `functionsDir` config option. **Do NOT** modify the main Hono `app` instance or create standalone Express/Fastify servers. Instead, drop a TypeScript file in the `functions/` directory and Rebase will auto-mount it.
9
+
10
+ ## Overview
11
+
12
+ Custom functions let you add arbitrary HTTP endpoints to your Rebase backend. They follow the same **file-based discovery** pattern as collections and cron jobs:
13
+
14
+ 1. Create a TypeScript file in your `backend/functions/` directory
15
+ 2. Default-export a **Hono app** (or a factory function that returns one)
16
+ 3. Rebase auto-mounts it at `/api/functions/{filename}`
17
+
18
+ ## Setup
19
+
20
+ Enable custom functions by adding `functionsDir` to your backend config:
21
+
22
+ ```typescript
23
+ const backend = await initializeRebaseBackend({
24
+ // ... other config
25
+ functionsDir: path.resolve(__dirname, "../functions"), // ← add this
26
+ });
27
+ ```
28
+
29
+ ## Creating a Function
30
+
31
+ Each file default-exports a Hono app:
32
+
33
+ ```typescript
34
+ // backend/functions/send-invoice.ts
35
+ import { Hono } from "hono";
36
+
37
+ const app = new Hono();
38
+
39
+ app.post("/", async (c) => {
40
+ const { orderId, email } = await c.req.json();
41
+
42
+ // Your custom logic here — send email, call Stripe, generate PDF, etc.
43
+ console.log(`Sending invoice for order ${orderId} to ${email}`);
44
+
45
+ return c.json({ success: true, message: `Invoice sent to ${email}` });
46
+ });
47
+
48
+ app.get("/status/:id", async (c) => {
49
+ const id = c.req.param("id");
50
+ return c.json({ invoiceId: id, status: "sent" });
51
+ });
52
+
53
+ export default app;
54
+ ```
55
+
56
+ This auto-mounts as:
57
+ - `POST /api/functions/send-invoice`
58
+ - `GET /api/functions/send-invoice/status/:id`
59
+
60
+ The **filename** (without extension) becomes the route prefix.
61
+
62
+ ## Factory Pattern
63
+
64
+ You can also export a factory function:
65
+
66
+ ```typescript
67
+ // backend/functions/webhooks.ts
68
+ import { Hono } from "hono";
69
+
70
+ export default function () {
71
+ const app = new Hono();
72
+
73
+ app.post("/stripe", async (c) => {
74
+ const body = await c.req.text();
75
+ // Verify Stripe signature, process event
76
+ return c.json({ received: true });
77
+ });
78
+
79
+ app.post("/github", async (c) => {
80
+ const payload = await c.req.json();
81
+ // Process GitHub webhook
82
+ return c.json({ received: true });
83
+ });
84
+
85
+ return app;
86
+ }
87
+ ```
88
+
89
+ ## Accessing Auth & Services
90
+
91
+ Custom functions run within the Hono middleware chain, so you have access to auth context:
92
+
93
+ ```typescript
94
+ // backend/functions/admin-export.ts
95
+ import { Hono } from "hono";
96
+ import type { HonoEnv } from "@rebasepro/server";
97
+
98
+ const app = new Hono<HonoEnv>();
99
+
100
+ app.get("/", async (c) => {
101
+ // Access the authenticated user from middleware
102
+ const user = c.get("user");
103
+ if (!user) {
104
+ return c.json({ error: "Unauthorized" }, 401);
105
+ }
106
+
107
+ // Access the data driver to query collections
108
+ const driver = c.get("driver");
109
+ const entities = await driver.fetchCollection("products", {
110
+ limit: 1000,
111
+ orderBy: "created_at",
112
+ order: "desc"
113
+ });
114
+
115
+ return c.json({ data: entities });
116
+ });
117
+
118
+ export default app;
119
+ ```
120
+
121
+ ### Use the `rebase` singleton for platform services — not raw SDKs
122
+
123
+ > **🚨 CRITICAL FOR AGENTS:** For data, storage, auth, and email inside a
124
+ > function/hook/job, use the configured platform services on the **`rebase`**
125
+ > singleton. **Never** import a cloud provider SDK directly to reimplement what
126
+ > the platform already provides.
127
+
128
+ ```typescript
129
+ import { rebase } from "@rebasepro/server";
130
+
131
+ await rebase.data.collection("orders").find({ where: { status: ["==", "paid"] } });
132
+ await rebase.storage.putObject({ key, file }); // → storageUrl (gs://|s3://|local://)
133
+ await rebase.email.send({ to, subject, html });
134
+ ```
135
+
136
+ | Need | ✅ Use | ❌ Never import directly |
137
+ |------|--------|--------------------------|
138
+ | Object storage | `rebase.storage` (see **rebase-storage** skill) | `@aws-sdk/client-s3`, `@google-cloud/storage` |
139
+ | Database / collections | `rebase.data` (or `c.get("driver")`) | `pg`, `drizzle` clients by hand |
140
+ | Email | `rebase.email` | `nodemailer`, provider SDKs |
141
+ | Auth / users | `rebase.auth` / `c.get("user")` | custom JWT parsing |
142
+
143
+ Importing a provider SDK hardcodes one backend, bypasses the app's config
144
+ (`STORAGE_TYPE`, `DATABASE_URL`, SMTP, …), and defeats the point of the platform.
145
+ The only code that touches provider SDKs is the adapters **inside**
146
+ `@rebasepro/server`.
147
+
148
+ ### Reserved Identity Values in `c.get("user")`
149
+
150
+ The `user` object set by the auth middleware uses reserved values for system identities:
151
+
152
+ | Auth Method | `user.userId` | `user.roles` |
153
+ |---|---|---|
154
+ | JWT (end-user) | Real user ID | User's assigned roles |
155
+ | Service Key | `"service"` | `["admin"]` |
156
+ | API Key (default) | `"api-key:{id}"` | `["service"]` |
157
+ | API Key (admin) | `"api-key:{id}"` | `["admin", "service"]` |
158
+ | Anonymous | `"anon"` | `["anon"]` |
159
+
160
+ > **TIP:** Use these to differentiate internal vs. external callers in your custom functions:
161
+ > ```typescript
162
+ > app.get("/sensitive-data", async (c) => {
163
+ > const user = c.get("user");
164
+ > const isInternal = user?.userId === "service" || user?.roles?.includes("admin");
165
+ > // Return full or masked data based on identity
166
+ > });
167
+ > ```
168
+
169
+ ## Invoking Functions from the Frontend
170
+
171
+ > **CRITICAL FOR AGENTS**: When calling custom backend functions from the frontend, **ALWAYS** use `client.functions.invoke()`. **NEVER** use raw `fetch()`, manually construct URLs, or manually extract auth tokens from `localStorage`. The SDK handles all of this automatically.
172
+
173
+ The `@rebasepro/client` SDK provides a `functions` namespace that handles:
174
+ - **Automatic routing** — appends `/api/functions/{name}` to the client's configured `baseUrl`
175
+ - **Automatic authentication** — injects the current session's JWT into the `Authorization: Bearer` header
176
+ - **Standardized errors** — throws `RebaseApiError` on non-2xx responses, matching the behavior of collection methods
177
+ - **401 retry** — automatically attempts token refresh on unauthorized responses
178
+
179
+ ### Basic Usage
180
+
181
+ ```typescript
182
+ // Invoke a function by name — auth token is injected automatically
183
+ const result = await client.functions.invoke<{ job: JobData }>('extract-job', {
184
+ url: 'https://example.com/job-posting',
185
+ html: htmlContent,
186
+ });
187
+ console.log(result.job.title);
188
+ ```
189
+
190
+ ### With Options
191
+
192
+ ```typescript
193
+ // Custom HTTP method
194
+ const status = await client.functions.invoke<{ status: string }>('send-invoice', undefined, {
195
+ method: 'GET',
196
+ path: `status/${invoiceId}`,
197
+ });
198
+
199
+ // DELETE request
200
+ await client.functions.invoke('cleanup', { olderThan: '30d' }, {
201
+ method: 'DELETE',
202
+ });
203
+ ```
204
+
205
+ ### TypeScript Generics
206
+
207
+ Use the generic type parameter to get full type safety on the response:
208
+
209
+ ```typescript
210
+ interface ExtractResult {
211
+ job: {
212
+ title: string;
213
+ company_name: string;
214
+ description_md: string;
215
+ };
216
+ }
217
+
218
+ const result = await client.functions.invoke<ExtractResult>('extract-job', { url });
219
+ // result.job.title is typed as string
220
+ ```
221
+
222
+ ### Error Handling
223
+
224
+ Errors follow the same pattern as collection methods:
225
+
226
+ ```typescript
227
+ import { RebaseApiError } from '@rebasepro/client';
228
+
229
+ try {
230
+ const result = await client.functions.invoke('process-payment', { orderId });
231
+ } catch (err) {
232
+ if (err instanceof RebaseApiError) {
233
+ console.error(`Status ${err.status}: ${err.message}`);
234
+ // err.code and err.details are also available
235
+ }
236
+ }
237
+ ```
238
+
239
+ ### ❌ Anti-Pattern — Do NOT Do This
240
+
241
+ ```typescript
242
+ // WRONG: Manual fetch with manual URL and manual token extraction
243
+ const token = JSON.parse(localStorage.getItem('rebase_auth') || '{}').accessToken;
244
+ const res = await fetch(`${apiUrl}/api/functions/extract-job`, {
245
+ method: 'POST',
246
+ headers: {
247
+ 'Content-Type': 'application/json',
248
+ 'Authorization': `Bearer ${token}`,
249
+ },
250
+ body: JSON.stringify({ url }),
251
+ });
252
+ ```
253
+
254
+ ### ✅ Correct Pattern
255
+
256
+ ```typescript
257
+ // RIGHT: SDK handles URL, auth, Content-Type, and error handling
258
+ const result = await client.functions.invoke('extract-job', { url });
259
+ ```
260
+
261
+ ## Common Use Cases
262
+
263
+ - **Webhook handlers** — Stripe, GitHub, Slack, Twilio incoming webhooks
264
+ - **Payment processing** — Custom checkout or subscription logic
265
+ - **PDF/report generation** — Server-side document rendering
266
+ - **Third-party API integrations** — Proxy or aggregate external APIs
267
+ - **Custom auth flows** — Magic links, phone verification, SSO
268
+ - **Data export** — CSV/Excel downloads of collection data
269
+ - **Health checks** — Custom readiness/liveness probes
270
+
271
+ ## File Discovery Rules
272
+
273
+ - Files must be `.ts` or `.js` (not `.d.ts`, not `.test.*`)
274
+ - `index.ts` / `index.js` are ignored
275
+ - Each file's default export must be a Hono app or a factory returning one
276
+ - The loader uses duck-typing (`fetch()` + `routes` array) — any Hono-compatible instance works
277
+
278
+ ## References
279
+
280
+ - **Documentation:** [rebase.pro/docs](https://rebase.pro/docs)
281
+ - **GitHub:** [github.com/rebasepro/rebase](https://github.com/rebasepro/rebase)