@daylight-labs/sharedb-mcp 0.1.0
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.
- package/dist/api-client.d.ts +175 -0
- package/dist/api-client.js +65 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +61 -0
- package/dist/resources/index.d.ts +13 -0
- package/dist/resources/index.js +638 -0
- package/dist/tools/auth.d.ts +31 -0
- package/dist/tools/auth.js +126 -0
- package/dist/tools/data.d.ts +127 -0
- package/dist/tools/data.js +290 -0
- package/dist/tools/migrations.d.ts +114 -0
- package/dist/tools/migrations.js +272 -0
- package/dist/tools/schema.d.ts +83 -0
- package/dist/tools/schema.js +289 -0
- package/package.json +38 -0
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
export const resources = [
|
|
2
|
+
{
|
|
3
|
+
uri: 'sharedb://getting-started',
|
|
4
|
+
name: 'ShareDB: Getting Started',
|
|
5
|
+
description: 'Overview of ShareDB - a managed PostgreSQL backend for apps. READ THIS FIRST when building an app that needs a database.',
|
|
6
|
+
mimeType: 'text/markdown',
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
uri: 'sharedb://rls-templates/row-ownership',
|
|
10
|
+
name: 'RLS Pattern: Row Ownership',
|
|
11
|
+
description: 'RLS policy pattern for user-owned rows',
|
|
12
|
+
mimeType: 'text/markdown',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
uri: 'sharedb://rls-templates/public-read',
|
|
16
|
+
name: 'RLS Pattern: Public Read, Owner Write',
|
|
17
|
+
description: 'RLS policy pattern for public read access with owner-only write',
|
|
18
|
+
mimeType: 'text/markdown',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
uri: 'sharedb://rls-templates/team-based',
|
|
22
|
+
name: 'RLS Pattern: Team-Based Access',
|
|
23
|
+
description: 'RLS policy pattern for team/organization-based access',
|
|
24
|
+
mimeType: 'text/markdown',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
uri: 'sharedb://guides/auth-integration',
|
|
28
|
+
name: 'Auth Integration Guide',
|
|
29
|
+
description: 'How to integrate ShareDB authentication into your app',
|
|
30
|
+
mimeType: 'text/markdown',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
uri: 'sharedb://guides/postgrest-usage',
|
|
34
|
+
name: 'PostgREST Usage Guide',
|
|
35
|
+
description: 'How to query data via PostgREST API',
|
|
36
|
+
mimeType: 'text/markdown',
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
const resourceContent = {
|
|
40
|
+
'sharedb://getting-started': `# ShareDB: Your App's Backend
|
|
41
|
+
|
|
42
|
+
ShareDB is a managed PostgreSQL backend that provides everything you need to build data-driven applications.
|
|
43
|
+
|
|
44
|
+
## What ShareDB Provides
|
|
45
|
+
|
|
46
|
+
- **PostgreSQL Database**: A dedicated database for your app with full SQL support
|
|
47
|
+
- **Authentication Service**: User registration, login, JWT tokens, and session management
|
|
48
|
+
- **PostgREST API**: Automatic REST API generated from your database schema
|
|
49
|
+
- **Row Level Security**: Built-in patterns for securing data with two role types:
|
|
50
|
+
- **Regular users**: App users who own their own data
|
|
51
|
+
- **Admins**: App builders who manage reference/shared data
|
|
52
|
+
- **Schema Migrations**: Version-controlled database changes with rollback support
|
|
53
|
+
|
|
54
|
+
## When to Use ShareDB
|
|
55
|
+
|
|
56
|
+
Use ShareDB when building ANY app that needs:
|
|
57
|
+
- Persistent data storage
|
|
58
|
+
- A REST API for your frontend
|
|
59
|
+
- User accounts and authentication (optional - works great for single-user personal apps too!)
|
|
60
|
+
|
|
61
|
+
**Works for all app sizes**:
|
|
62
|
+
- **Personal apps**: Budget trackers, habit trackers, personal wikis, journals - even single-user apps benefit from a real database
|
|
63
|
+
- **Multi-user apps**: Todo apps, note-taking apps, project management tools, social apps, dashboards, CRMs
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
### 1. Create a Database
|
|
68
|
+
|
|
69
|
+
\`\`\`
|
|
70
|
+
Use the create_database tool:
|
|
71
|
+
- name: "my_app" (lowercase, underscores ok)
|
|
72
|
+
- display_name: "My App"
|
|
73
|
+
- environment: "development"
|
|
74
|
+
\`\`\`
|
|
75
|
+
|
|
76
|
+
### 2. Design Your Schema
|
|
77
|
+
|
|
78
|
+
\`\`\`
|
|
79
|
+
Use the stage_change tool to add tables:
|
|
80
|
+
|
|
81
|
+
stage_change({
|
|
82
|
+
database_id: "my_app",
|
|
83
|
+
operation: "CREATE_TABLE",
|
|
84
|
+
params: {
|
|
85
|
+
tableName: "todos",
|
|
86
|
+
columns: [
|
|
87
|
+
{ name: "id", type: "UUID", primaryKey: true, defaultValue: "uuid_generate_v4()" },
|
|
88
|
+
{ name: "user_id", type: "UUID", nullable: false, defaultValue: "current_user_id()" },
|
|
89
|
+
{ name: "title", type: "TEXT", nullable: false },
|
|
90
|
+
{ name: "completed", type: "BOOLEAN", defaultValue: "false" },
|
|
91
|
+
{ name: "created_at", type: "TIMESTAMPTZ", defaultValue: "NOW()" }
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
\`\`\`
|
|
96
|
+
|
|
97
|
+
### 3. Preview and Apply
|
|
98
|
+
|
|
99
|
+
\`\`\`
|
|
100
|
+
preview_changes({ database_id: "my_app" })
|
|
101
|
+
apply_changes({ database_id: "my_app", description: "Add todos table" })
|
|
102
|
+
\`\`\`
|
|
103
|
+
|
|
104
|
+
### 4. Connect Your App
|
|
105
|
+
|
|
106
|
+
Your app can now:
|
|
107
|
+
- Authenticate users via \`/auth/login\`, \`/auth/register\`
|
|
108
|
+
- Query data via PostgREST: \`GET /api/todos\`, \`POST /api/todos\`, etc.
|
|
109
|
+
- Include the JWT in the Authorization header
|
|
110
|
+
|
|
111
|
+
## Available Tools
|
|
112
|
+
|
|
113
|
+
| Tool | Purpose |
|
|
114
|
+
|------|---------|
|
|
115
|
+
| \`create_database\` | Create a new app database |
|
|
116
|
+
| \`list_databases\` | List all your databases |
|
|
117
|
+
| \`get_database_schema\` | View tables, columns, indexes |
|
|
118
|
+
| \`stage_change\` | Stage schema changes (CREATE_TABLE, ADD_COLUMN, etc.) |
|
|
119
|
+
| \`preview_changes\` | See DDL before applying |
|
|
120
|
+
| \`apply_changes\` | Apply staged changes as a migration |
|
|
121
|
+
| \`rollback_migration\` | Undo the last migration |
|
|
122
|
+
|
|
123
|
+
## Resources
|
|
124
|
+
|
|
125
|
+
- \`sharedb://guides/auth-integration\` - How to add auth to your app
|
|
126
|
+
- \`sharedb://guides/postgrest-usage\` - How to query data via REST
|
|
127
|
+
- \`sharedb://rls-templates/*\` - Security patterns for multi-user apps
|
|
128
|
+
`,
|
|
129
|
+
'sharedb://rls-templates/row-ownership': `# Row Ownership RLS Pattern
|
|
130
|
+
|
|
131
|
+
This pattern restricts row access to the user who owns the row.
|
|
132
|
+
|
|
133
|
+
## SQL Implementation
|
|
134
|
+
|
|
135
|
+
\`\`\`sql
|
|
136
|
+
-- Enable RLS on the table
|
|
137
|
+
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
|
|
138
|
+
|
|
139
|
+
-- Create policy for user-owned rows
|
|
140
|
+
CREATE POLICY user_owns_row ON your_table
|
|
141
|
+
FOR ALL
|
|
142
|
+
USING (user_id = current_user_id());
|
|
143
|
+
\`\`\`
|
|
144
|
+
|
|
145
|
+
## Usage
|
|
146
|
+
|
|
147
|
+
1. Ensure your table has a \`user_id\` column of type UUID
|
|
148
|
+
2. The \`current_user_id()\` function extracts the user ID from the JWT claims
|
|
149
|
+
3. Users can only see/modify rows where \`user_id\` matches their ID
|
|
150
|
+
|
|
151
|
+
## Example Table
|
|
152
|
+
|
|
153
|
+
\`\`\`sql
|
|
154
|
+
CREATE TABLE todos (
|
|
155
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
156
|
+
user_id UUID NOT NULL DEFAULT current_user_id(),
|
|
157
|
+
title TEXT NOT NULL,
|
|
158
|
+
completed BOOLEAN DEFAULT FALSE,
|
|
159
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;
|
|
163
|
+
|
|
164
|
+
CREATE POLICY todos_user_isolation ON todos
|
|
165
|
+
FOR ALL
|
|
166
|
+
USING (user_id = current_user_id());
|
|
167
|
+
\`\`\`
|
|
168
|
+
`,
|
|
169
|
+
'sharedb://rls-templates/public-read': `# Public Read, Owner Write RLS Pattern
|
|
170
|
+
|
|
171
|
+
This pattern allows anyone to read rows but only the owner can modify them.
|
|
172
|
+
|
|
173
|
+
## SQL Implementation
|
|
174
|
+
|
|
175
|
+
\`\`\`sql
|
|
176
|
+
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
|
|
177
|
+
|
|
178
|
+
-- Anyone can read
|
|
179
|
+
CREATE POLICY public_read ON your_table
|
|
180
|
+
FOR SELECT
|
|
181
|
+
USING (true);
|
|
182
|
+
|
|
183
|
+
-- Only owner can insert
|
|
184
|
+
CREATE POLICY owner_insert ON your_table
|
|
185
|
+
FOR INSERT
|
|
186
|
+
WITH CHECK (user_id = current_user_id());
|
|
187
|
+
|
|
188
|
+
-- Only owner can update
|
|
189
|
+
CREATE POLICY owner_update ON your_table
|
|
190
|
+
FOR UPDATE
|
|
191
|
+
USING (user_id = current_user_id())
|
|
192
|
+
WITH CHECK (user_id = current_user_id());
|
|
193
|
+
|
|
194
|
+
-- Only owner can delete
|
|
195
|
+
CREATE POLICY owner_delete ON your_table
|
|
196
|
+
FOR DELETE
|
|
197
|
+
USING (user_id = current_user_id());
|
|
198
|
+
\`\`\`
|
|
199
|
+
|
|
200
|
+
## Example: Blog Posts
|
|
201
|
+
|
|
202
|
+
\`\`\`sql
|
|
203
|
+
CREATE TABLE posts (
|
|
204
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
205
|
+
user_id UUID NOT NULL DEFAULT current_user_id(),
|
|
206
|
+
title TEXT NOT NULL,
|
|
207
|
+
content TEXT NOT NULL,
|
|
208
|
+
published BOOLEAN DEFAULT FALSE,
|
|
209
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
|
|
213
|
+
|
|
214
|
+
-- Public can read published posts
|
|
215
|
+
CREATE POLICY posts_public_read ON posts
|
|
216
|
+
FOR SELECT
|
|
217
|
+
USING (published = true OR user_id = current_user_id());
|
|
218
|
+
|
|
219
|
+
-- Author can insert
|
|
220
|
+
CREATE POLICY posts_author_insert ON posts
|
|
221
|
+
FOR INSERT
|
|
222
|
+
WITH CHECK (user_id = current_user_id());
|
|
223
|
+
|
|
224
|
+
-- Author can update own posts
|
|
225
|
+
CREATE POLICY posts_author_update ON posts
|
|
226
|
+
FOR UPDATE
|
|
227
|
+
USING (user_id = current_user_id());
|
|
228
|
+
|
|
229
|
+
-- Author can delete own posts
|
|
230
|
+
CREATE POLICY posts_author_delete ON posts
|
|
231
|
+
FOR DELETE
|
|
232
|
+
USING (user_id = current_user_id());
|
|
233
|
+
\`\`\`
|
|
234
|
+
`,
|
|
235
|
+
'sharedb://rls-templates/team-based': `# Team-Based Access RLS Pattern
|
|
236
|
+
|
|
237
|
+
This pattern restricts access based on team/organization membership.
|
|
238
|
+
|
|
239
|
+
## Required Tables
|
|
240
|
+
|
|
241
|
+
\`\`\`sql
|
|
242
|
+
-- Teams table
|
|
243
|
+
CREATE TABLE teams (
|
|
244
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
245
|
+
name TEXT NOT NULL,
|
|
246
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
-- Team memberships
|
|
250
|
+
CREATE TABLE team_members (
|
|
251
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
252
|
+
team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
|
|
253
|
+
user_id UUID NOT NULL,
|
|
254
|
+
role TEXT NOT NULL DEFAULT 'member',
|
|
255
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
256
|
+
UNIQUE(team_id, user_id)
|
|
257
|
+
);
|
|
258
|
+
\`\`\`
|
|
259
|
+
|
|
260
|
+
## Helper Function
|
|
261
|
+
|
|
262
|
+
\`\`\`sql
|
|
263
|
+
CREATE OR REPLACE FUNCTION user_team_ids()
|
|
264
|
+
RETURNS UUID[] AS $$
|
|
265
|
+
SELECT COALESCE(
|
|
266
|
+
ARRAY_AGG(team_id),
|
|
267
|
+
ARRAY[]::UUID[]
|
|
268
|
+
)
|
|
269
|
+
FROM team_members
|
|
270
|
+
WHERE user_id = current_user_id();
|
|
271
|
+
$$ LANGUAGE sql STABLE;
|
|
272
|
+
\`\`\`
|
|
273
|
+
|
|
274
|
+
## Team Resource Policy
|
|
275
|
+
|
|
276
|
+
\`\`\`sql
|
|
277
|
+
CREATE TABLE projects (
|
|
278
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
279
|
+
team_id UUID NOT NULL REFERENCES teams(id),
|
|
280
|
+
name TEXT NOT NULL,
|
|
281
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
|
|
285
|
+
|
|
286
|
+
-- Team members can access their team's projects
|
|
287
|
+
CREATE POLICY projects_team_access ON projects
|
|
288
|
+
FOR ALL
|
|
289
|
+
USING (team_id = ANY(user_team_ids()));
|
|
290
|
+
\`\`\`
|
|
291
|
+
`,
|
|
292
|
+
'sharedb://guides/auth-integration': `# ShareDB Auth Integration Guide
|
|
293
|
+
|
|
294
|
+
This guide explains how to integrate ShareDB authentication into your app.
|
|
295
|
+
|
|
296
|
+
## Overview
|
|
297
|
+
|
|
298
|
+
ShareDB provides a centralized authentication service that issues JWTs. Your app:
|
|
299
|
+
1. Collects user credentials (email/password or OAuth)
|
|
300
|
+
2. Calls ShareDB auth endpoints
|
|
301
|
+
3. Stores the returned tokens
|
|
302
|
+
4. Includes the access token in PostgREST requests
|
|
303
|
+
|
|
304
|
+
## Authentication Flow
|
|
305
|
+
|
|
306
|
+
\`\`\`
|
|
307
|
+
┌──────────────────┐ ┌──────────────────┐
|
|
308
|
+
│ Your App │ │ ShareDB Auth │
|
|
309
|
+
└────────┬─────────┘ └────────┬─────────┘
|
|
310
|
+
│ │
|
|
311
|
+
│ 1. POST /auth/login │
|
|
312
|
+
│ { email, password } │
|
|
313
|
+
│───────────────────────────>│
|
|
314
|
+
│ │
|
|
315
|
+
│ 2. { accessToken, │
|
|
316
|
+
│ refreshToken } │
|
|
317
|
+
│<───────────────────────────│
|
|
318
|
+
│ │
|
|
319
|
+
│ Store tokens locally │
|
|
320
|
+
│ │
|
|
321
|
+
│ 3. GET /api/todos │
|
|
322
|
+
│ Authorization: Bearer ... │
|
|
323
|
+
│───────────────────────────>│ PostgREST
|
|
324
|
+
│ │
|
|
325
|
+
│ 4. [ user's todos ] │
|
|
326
|
+
│<───────────────────────────│
|
|
327
|
+
│ │
|
|
328
|
+
\`\`\`
|
|
329
|
+
|
|
330
|
+
## Auth Endpoints
|
|
331
|
+
|
|
332
|
+
### Register
|
|
333
|
+
\`\`\`
|
|
334
|
+
POST /auth/register
|
|
335
|
+
Content-Type: application/json
|
|
336
|
+
|
|
337
|
+
{
|
|
338
|
+
"email": "user@example.com",
|
|
339
|
+
"password": "secure-password",
|
|
340
|
+
"name": "John Doe"
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
Response: { accessToken, refreshToken, user }
|
|
344
|
+
\`\`\`
|
|
345
|
+
|
|
346
|
+
### Login
|
|
347
|
+
\`\`\`
|
|
348
|
+
POST /auth/login
|
|
349
|
+
Content-Type: application/json
|
|
350
|
+
|
|
351
|
+
{
|
|
352
|
+
"email": "user@example.com",
|
|
353
|
+
"password": "secure-password"
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
Response: { accessToken, refreshToken, user }
|
|
357
|
+
\`\`\`
|
|
358
|
+
|
|
359
|
+
### Refresh Token
|
|
360
|
+
\`\`\`
|
|
361
|
+
POST /auth/refresh
|
|
362
|
+
Content-Type: application/json
|
|
363
|
+
|
|
364
|
+
{
|
|
365
|
+
"refreshToken": "..."
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
Response: { accessToken, refreshToken }
|
|
369
|
+
\`\`\`
|
|
370
|
+
|
|
371
|
+
### Get Current User
|
|
372
|
+
\`\`\`
|
|
373
|
+
GET /auth/me
|
|
374
|
+
Authorization: Bearer <accessToken>
|
|
375
|
+
|
|
376
|
+
Response: { id, email, name, ... }
|
|
377
|
+
\`\`\`
|
|
378
|
+
|
|
379
|
+
## React Example
|
|
380
|
+
|
|
381
|
+
\`\`\`tsx
|
|
382
|
+
import { useState, createContext, useContext } from 'react';
|
|
383
|
+
|
|
384
|
+
interface AuthContext {
|
|
385
|
+
user: User | null;
|
|
386
|
+
login: (email: string, password: string) => Promise<void>;
|
|
387
|
+
logout: () => void;
|
|
388
|
+
getToken: () => string | null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const AuthContext = createContext<AuthContext | null>(null);
|
|
392
|
+
|
|
393
|
+
export function AuthProvider({ children }) {
|
|
394
|
+
const [user, setUser] = useState<User | null>(null);
|
|
395
|
+
const [accessToken, setAccessToken] = useState<string | null>(
|
|
396
|
+
localStorage.getItem('accessToken')
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
async function login(email: string, password: string) {
|
|
400
|
+
const res = await fetch('/auth/login', {
|
|
401
|
+
method: 'POST',
|
|
402
|
+
headers: { 'Content-Type': 'application/json' },
|
|
403
|
+
body: JSON.stringify({ email, password }),
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
if (!res.ok) throw new Error('Login failed');
|
|
407
|
+
|
|
408
|
+
const { accessToken, refreshToken, user } = await res.json();
|
|
409
|
+
localStorage.setItem('accessToken', accessToken);
|
|
410
|
+
localStorage.setItem('refreshToken', refreshToken);
|
|
411
|
+
setAccessToken(accessToken);
|
|
412
|
+
setUser(user);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function logout() {
|
|
416
|
+
localStorage.removeItem('accessToken');
|
|
417
|
+
localStorage.removeItem('refreshToken');
|
|
418
|
+
setAccessToken(null);
|
|
419
|
+
setUser(null);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function getToken() {
|
|
423
|
+
return accessToken;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return (
|
|
427
|
+
<AuthContext.Provider value={{ user, login, logout, getToken }}>
|
|
428
|
+
{children}
|
|
429
|
+
</AuthContext.Provider>
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export function useAuth() {
|
|
434
|
+
const ctx = useContext(AuthContext);
|
|
435
|
+
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
|
|
436
|
+
return ctx;
|
|
437
|
+
}
|
|
438
|
+
\`\`\`
|
|
439
|
+
|
|
440
|
+
## Making Authenticated API Requests
|
|
441
|
+
|
|
442
|
+
\`\`\`tsx
|
|
443
|
+
function useFetch() {
|
|
444
|
+
const { getToken } = useAuth();
|
|
445
|
+
|
|
446
|
+
return async function fetchWithAuth(url: string, options?: RequestInit) {
|
|
447
|
+
const token = getToken();
|
|
448
|
+
return fetch(url, {
|
|
449
|
+
...options,
|
|
450
|
+
headers: {
|
|
451
|
+
...options?.headers,
|
|
452
|
+
Authorization: \`Bearer \${token}\`,
|
|
453
|
+
},
|
|
454
|
+
});
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
\`\`\`
|
|
458
|
+
`,
|
|
459
|
+
'sharedb://guides/postgrest-usage': `# PostgREST Usage Guide
|
|
460
|
+
|
|
461
|
+
PostgREST automatically generates a REST API from your PostgreSQL schema.
|
|
462
|
+
|
|
463
|
+
## Base URL
|
|
464
|
+
|
|
465
|
+
Your app's PostgREST endpoint is:
|
|
466
|
+
\`\`\`
|
|
467
|
+
https://your-app.sharedb.example.com/api
|
|
468
|
+
\`\`\`
|
|
469
|
+
|
|
470
|
+
## Authentication
|
|
471
|
+
|
|
472
|
+
Include the JWT in the Authorization header:
|
|
473
|
+
\`\`\`
|
|
474
|
+
Authorization: Bearer <your-jwt-token>
|
|
475
|
+
\`\`\`
|
|
476
|
+
|
|
477
|
+
## Basic CRUD Operations
|
|
478
|
+
|
|
479
|
+
### Read All Rows
|
|
480
|
+
\`\`\`
|
|
481
|
+
GET /api/todos
|
|
482
|
+
|
|
483
|
+
Response: [{ id, title, completed, ... }, ...]
|
|
484
|
+
\`\`\`
|
|
485
|
+
|
|
486
|
+
### Read Single Row
|
|
487
|
+
\`\`\`
|
|
488
|
+
GET /api/todos?id=eq.uuid-here
|
|
489
|
+
|
|
490
|
+
Response: [{ id, title, completed, ... }]
|
|
491
|
+
\`\`\`
|
|
492
|
+
|
|
493
|
+
### Create Row
|
|
494
|
+
\`\`\`
|
|
495
|
+
POST /api/todos
|
|
496
|
+
Content-Type: application/json
|
|
497
|
+
|
|
498
|
+
{ "title": "New todo", "completed": false }
|
|
499
|
+
|
|
500
|
+
Response: { id, title, completed, ... }
|
|
501
|
+
\`\`\`
|
|
502
|
+
|
|
503
|
+
### Update Row
|
|
504
|
+
\`\`\`
|
|
505
|
+
PATCH /api/todos?id=eq.uuid-here
|
|
506
|
+
Content-Type: application/json
|
|
507
|
+
|
|
508
|
+
{ "completed": true }
|
|
509
|
+
|
|
510
|
+
Response: { id, title, completed, ... }
|
|
511
|
+
\`\`\`
|
|
512
|
+
|
|
513
|
+
### Delete Row
|
|
514
|
+
\`\`\`
|
|
515
|
+
DELETE /api/todos?id=eq.uuid-here
|
|
516
|
+
\`\`\`
|
|
517
|
+
|
|
518
|
+
## Filtering
|
|
519
|
+
|
|
520
|
+
PostgREST supports powerful filtering:
|
|
521
|
+
|
|
522
|
+
| Operator | Meaning | Example |
|
|
523
|
+
|----------|---------|---------|
|
|
524
|
+
| eq | equals | \`?status=eq.active\` |
|
|
525
|
+
| neq | not equals | \`?status=neq.deleted\` |
|
|
526
|
+
| gt | greater than | \`?price=gt.100\` |
|
|
527
|
+
| gte | greater or equal | \`?price=gte.100\` |
|
|
528
|
+
| lt | less than | \`?price=lt.50\` |
|
|
529
|
+
| lte | less or equal | \`?price=lte.50\` |
|
|
530
|
+
| like | pattern match | \`?title=like.*foo*\` |
|
|
531
|
+
| ilike | case-insensitive | \`?title=ilike.*foo*\` |
|
|
532
|
+
| in | in list | \`?status=in.(active,pending)\` |
|
|
533
|
+
| is | is null/true/false | \`?deleted=is.null\` |
|
|
534
|
+
|
|
535
|
+
## Ordering
|
|
536
|
+
|
|
537
|
+
\`\`\`
|
|
538
|
+
GET /api/todos?order=created_at.desc
|
|
539
|
+
GET /api/todos?order=priority.asc,created_at.desc
|
|
540
|
+
\`\`\`
|
|
541
|
+
|
|
542
|
+
## Pagination
|
|
543
|
+
|
|
544
|
+
\`\`\`
|
|
545
|
+
GET /api/todos?limit=10&offset=0
|
|
546
|
+
\`\`\`
|
|
547
|
+
|
|
548
|
+
## Selecting Columns
|
|
549
|
+
|
|
550
|
+
\`\`\`
|
|
551
|
+
GET /api/todos?select=id,title,completed
|
|
552
|
+
\`\`\`
|
|
553
|
+
|
|
554
|
+
## Embedding Related Data
|
|
555
|
+
|
|
556
|
+
If you have foreign key relationships:
|
|
557
|
+
|
|
558
|
+
\`\`\`
|
|
559
|
+
GET /api/todos?select=*,user:users(name,email)
|
|
560
|
+
\`\`\`
|
|
561
|
+
|
|
562
|
+
## JavaScript Client Example
|
|
563
|
+
|
|
564
|
+
\`\`\`javascript
|
|
565
|
+
class PostgRESTClient {
|
|
566
|
+
constructor(baseUrl, getToken) {
|
|
567
|
+
this.baseUrl = baseUrl;
|
|
568
|
+
this.getToken = getToken;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
async request(path, options = {}) {
|
|
572
|
+
const response = await fetch(\`\${this.baseUrl}\${path}\`, {
|
|
573
|
+
...options,
|
|
574
|
+
headers: {
|
|
575
|
+
'Content-Type': 'application/json',
|
|
576
|
+
Authorization: \`Bearer \${this.getToken()}\`,
|
|
577
|
+
...options.headers,
|
|
578
|
+
},
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
if (!response.ok) {
|
|
582
|
+
throw new Error(\`API error: \${response.status}\`);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
return response.json();
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
async list(table, params = {}) {
|
|
589
|
+
const query = new URLSearchParams(params).toString();
|
|
590
|
+
return this.request(\`/\${table}?\${query}\`);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
async get(table, id) {
|
|
594
|
+
const [row] = await this.request(\`/\${table}?id=eq.\${id}\`);
|
|
595
|
+
return row;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
async create(table, data) {
|
|
599
|
+
return this.request(\`/\${table}\`, {
|
|
600
|
+
method: 'POST',
|
|
601
|
+
body: JSON.stringify(data),
|
|
602
|
+
headers: { Prefer: 'return=representation' },
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
async update(table, id, data) {
|
|
607
|
+
return this.request(\`/\${table}?id=eq.\${id}\`, {
|
|
608
|
+
method: 'PATCH',
|
|
609
|
+
body: JSON.stringify(data),
|
|
610
|
+
headers: { Prefer: 'return=representation' },
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
async delete(table, id) {
|
|
615
|
+
return this.request(\`/\${table}?id=eq.\${id}\`, {
|
|
616
|
+
method: 'DELETE',
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
\`\`\`
|
|
621
|
+
`,
|
|
622
|
+
};
|
|
623
|
+
export function readResource(uri) {
|
|
624
|
+
const content = resourceContent[uri];
|
|
625
|
+
if (!content) {
|
|
626
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
627
|
+
}
|
|
628
|
+
const resource = resources.find((r) => r.uri === uri);
|
|
629
|
+
return {
|
|
630
|
+
contents: [
|
|
631
|
+
{
|
|
632
|
+
uri,
|
|
633
|
+
mimeType: resource?.mimeType || 'text/plain',
|
|
634
|
+
text: content,
|
|
635
|
+
},
|
|
636
|
+
],
|
|
637
|
+
};
|
|
638
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare const authTools: ({
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
database_id: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
required: never[];
|
|
13
|
+
};
|
|
14
|
+
} | {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: "object";
|
|
19
|
+
properties: {
|
|
20
|
+
database_id?: undefined;
|
|
21
|
+
};
|
|
22
|
+
required: never[];
|
|
23
|
+
};
|
|
24
|
+
})[];
|
|
25
|
+
export declare function handleAuthTool(name: string, args: Record<string, unknown>): Promise<{
|
|
26
|
+
content: Array<{
|
|
27
|
+
type: 'text';
|
|
28
|
+
text: string;
|
|
29
|
+
}>;
|
|
30
|
+
isError?: boolean;
|
|
31
|
+
}>;
|