@vettly/supabase 0.1.0 → 0.1.1

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 (2) hide show
  1. package/README.md +69 -187
  2. package/package.json +9 -19
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @vettly/supabase
2
2
 
3
- Vettly content moderation for Supabase Edge Functions. Deno-compatible, fetch-based client.
3
+ Vettly decision infrastructure for Supabase Edge Functions. Deno-compatible client with fetch-based transport for serverless environments.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,7 +8,7 @@ Vettly content moderation for Supabase Edge Functions. Deno-compatible, fetch-ba
8
8
  npm install @vettly/supabase
9
9
  ```
10
10
 
11
- Or with Deno in your Edge Function:
11
+ Or import directly in Deno:
12
12
 
13
13
  ```typescript
14
14
  import { moderate } from 'npm:@vettly/supabase'
@@ -21,246 +21,128 @@ import { moderate } from 'npm:@vettly/supabase'
21
21
  ```typescript
22
22
  import { createModerationHandler } from '@vettly/supabase'
23
23
 
24
- // Moderate all incoming content
25
24
  Deno.serve(createModerationHandler({
26
25
  policyId: 'default',
27
26
  onBlock: (result) => new Response(JSON.stringify({
28
27
  error: 'Content blocked',
29
- reason: result.categories.filter(c => c.flagged)
30
- }), { status: 403, headers: { 'Content-Type': 'application/json' } })
28
+ categories: result.categories
29
+ }), { status: 403 })
31
30
  }))
32
31
  ```
33
32
 
34
- ### Manual Control
33
+ ### Manual Integration
35
34
 
36
35
  ```typescript
37
- import { moderate } from '@vettly/supabase'
36
+ import { createClient } from '@vettly/supabase'
37
+
38
+ const vettly = createClient({
39
+ apiKey: Deno.env.get('VETTLY_API_KEY')!
40
+ })
38
41
 
39
42
  Deno.serve(async (req) => {
40
- const { content, userId } = await req.json()
43
+ const { content } = await req.json()
41
44
 
42
- // Moderate content first
43
- const result = await moderate(content, { policyId: 'strict' })
45
+ const result = await vettly.check(content, {
46
+ policyId: 'community-safe'
47
+ })
44
48
 
45
49
  if (result.action === 'block') {
46
50
  return new Response('Content blocked', { status: 403 })
47
51
  }
48
52
 
49
- // Content is safe, continue with your logic
50
- // await supabase.from('posts').insert({ content, userId })
51
-
52
- return new Response(JSON.stringify({ success: true }), {
53
- headers: { 'Content-Type': 'application/json' }
54
- })
53
+ return new Response('OK')
55
54
  })
56
55
  ```
57
56
 
58
- ### Middleware Pattern
59
-
60
- ```typescript
61
- import { withModeration } from '@vettly/supabase'
62
-
63
- const handler = withModeration(
64
- async (req, moderationResult) => {
65
- // Content already passed moderation
66
- const { content, userId } = await req.json()
67
-
68
- // Insert into database...
69
- // await supabase.from('posts').insert({ content, userId })
70
-
71
- return new Response(JSON.stringify({
72
- success: true,
73
- moderation: {
74
- decisionId: moderationResult.decisionId,
75
- safe: moderationResult.safe
76
- }
77
- }), { headers: { 'Content-Type': 'application/json' } })
78
- },
79
- { policyId: 'user-content' }
80
- )
81
-
82
- Deno.serve(handler)
83
- ```
84
-
85
- ## Configuration
86
-
87
- ### Environment Variable
88
-
89
- Set `VETTLY_API_KEY` in your Supabase project secrets:
57
+ ## API
90
58
 
91
- ```bash
92
- supabase secrets set VETTLY_API_KEY=your_api_key
93
- ```
59
+ ### `createClient(config)`
94
60
 
95
- ### Programmatic Configuration
61
+ Create a configured Vettly client.
96
62
 
97
63
  ```typescript
98
- import { createClient } from '@vettly/supabase'
99
-
100
- const vettly = createClient({
101
- apiKey: Deno.env.get('VETTLY_API_KEY')!,
102
- apiUrl: 'https://api.vettly.dev', // optional
103
- timeout: 30000 // optional, in ms
64
+ const client = createClient({
65
+ apiKey: 'sk_live_...',
66
+ apiUrl: 'https://api.vettly.dev' // optional
104
67
  })
105
68
 
106
- const result = await vettly.check('Hello world', { policyId: 'default' })
107
- ```
108
-
109
- ## API Reference
110
-
111
- ### `moderate(content, options?)`
112
-
113
- Moderate text content using the default client.
114
-
115
- ```typescript
116
- const result = await moderate('User generated content', {
117
- policyId: 'strict', // Policy to use (default: 'default')
118
- contentType: 'text', // 'text' | 'image' | 'video'
119
- language: 'en', // ISO 639-1 language code
120
- metadata: { userId: '123' }
121
- })
69
+ // Check text
70
+ const result = await client.check('user content', { policyId: 'default' })
122
71
 
123
- // Result:
124
- // {
125
- // decisionId: 'dec_123',
126
- // safe: true,
127
- // flagged: false,
128
- // action: 'allow',
129
- // categories: [{ category: 'hate_speech', score: 0.01, flagged: false }],
130
- // provider: 'openai',
131
- // latency: 150,
132
- // cost: 0.0001
133
- // }
72
+ // Check image
73
+ const result = await client.checkImage('https://...', { policyId: 'strict' })
134
74
  ```
135
75
 
136
- ### `moderateImage(imageUrl, options?)`
76
+ ### `moderate(content, options)`
137
77
 
138
- Moderate an image by URL.
78
+ Quick moderation without creating a client (uses `VETTLY_API_KEY` env var).
139
79
 
140
80
  ```typescript
141
- const result = await moderateImage('https://example.com/image.jpg', {
142
- policyId: 'images'
143
- })
81
+ import { moderate } from '@vettly/supabase'
82
+
83
+ const result = await moderate('user content', { policyId: 'default' })
144
84
  ```
145
85
 
146
86
  ### `createModerationHandler(config)`
147
87
 
148
- Create an Edge Function handler that moderates incoming requests.
88
+ Create an Edge Function handler that automatically moderates incoming requests.
149
89
 
150
90
  ```typescript
151
- import { createModerationHandler } from '@vettly/supabase'
152
-
153
- Deno.serve(createModerationHandler({
154
- apiKey: Deno.env.get('VETTLY_API_KEY'), // Optional, uses env var by default
155
- policyId: 'default',
156
-
157
- // Custom content extraction (default: reads req.json().content)
158
- getContent: async (req) => {
159
- const { message } = await req.json()
160
- return message
161
- },
162
-
163
- // Handle blocked content
164
- onBlock: (result, req) => {
165
- return new Response(JSON.stringify({ blocked: true }), { status: 403 })
166
- },
167
-
168
- // Handle flagged content (logged but allowed)
169
- onFlag: (result, req) => {
170
- console.log('Flagged content:', result.decisionId)
171
- },
172
-
173
- // Handle warnings
174
- onWarn: (result, req) => {
175
- console.log('Warning:', result.categories)
176
- },
177
-
178
- // Handle allowed content
179
- onAllow: (result, req) => {
180
- return new Response(JSON.stringify({ success: true }))
181
- },
182
-
183
- // Handle errors
184
- onError: (error, req) => {
185
- console.error('Moderation error:', error)
186
- return new Response('Error', { status: 500 })
91
+ import { createModerationHandler } from '@vettly/supabase/edge'
92
+
93
+ export default createModerationHandler({
94
+ policyId: 'community-safe',
95
+ field: 'content', // JSON field to moderate
96
+ onBlock: (result) => new Response('Blocked', { status: 403 }),
97
+ onAllow: (req, result) => {
98
+ // Continue processing
187
99
  }
188
- }))
100
+ })
189
101
  ```
190
102
 
191
103
  ### `withModeration(handler, config)`
192
104
 
193
- Middleware-style handler that moderates content before passing to your handler.
105
+ Wrap an existing Edge Function with moderation.
194
106
 
195
107
  ```typescript
196
- import { withModeration } from '@vettly/supabase'
108
+ import { withModeration } from '@vettly/supabase/edge'
197
109
 
198
- const handler = withModeration(
199
- async (req, moderationResult) => {
200
- // Your handler receives the moderation result
201
- console.log('Decision ID:', moderationResult.decisionId)
202
- console.log('Safe:', moderationResult.safe)
203
-
204
- // Process the request...
205
- return new Response(JSON.stringify({ success: true }))
206
- },
207
- { policyId: 'user-content' }
208
- )
209
-
210
- Deno.serve(handler)
211
- ```
212
-
213
- ### `createClient(config)`
214
-
215
- Create a configured Vettly client for more control.
110
+ const handler = async (req: Request) => {
111
+ // Your logic here
112
+ return new Response('OK')
113
+ }
216
114
 
217
- ```typescript
218
- const client = createClient({
219
- apiKey: 'vettly_...',
220
- apiUrl: 'https://api.vettly.dev',
221
- timeout: 30000
115
+ export default withModeration(handler, {
116
+ policyId: 'default',
117
+ field: 'body'
222
118
  })
223
-
224
- // Text moderation
225
- const textResult = await client.check('Hello world', { policyId: 'default' })
226
-
227
- // Image moderation
228
- const imageResult = await client.checkImage('https://...', { policyId: 'images' })
229
119
  ```
230
120
 
231
- ## Error Handling
121
+ ## Response Format
232
122
 
233
123
  ```typescript
234
- import { moderate, VettlyError, VettlyAuthError, VettlyRateLimitError } from '@vettly/supabase'
235
-
236
- try {
237
- const result = await moderate('content')
238
- } catch (error) {
239
- if (error instanceof VettlyAuthError) {
240
- console.error('Invalid API key')
241
- } else if (error instanceof VettlyRateLimitError) {
242
- console.error('Rate limited, retry after:', error.retryAfter)
243
- } else if (error instanceof VettlyError) {
244
- console.error('Vettly error:', error.code, error.message)
245
- }
124
+ interface ModerationResult {
125
+ decisionId: string
126
+ safe: boolean
127
+ flagged: boolean
128
+ action: 'allow' | 'warn' | 'flag' | 'block'
129
+ categories: Array<{
130
+ category: string
131
+ score: number
132
+ triggered: boolean
133
+ }>
134
+ latency: number
246
135
  }
247
136
  ```
248
137
 
249
- ## TypeScript Types
138
+ ## Environment Variables
250
139
 
251
- ```typescript
252
- import type {
253
- ModerationResult,
254
- ModerationOptions,
255
- Action,
256
- Category,
257
- CategoryScore,
258
- VettlyConfig,
259
- EdgeHandlerOptions,
260
- ModerationHandlerConfig
261
- } from '@vettly/supabase'
262
- ```
140
+ Set in your Supabase project settings:
141
+
142
+ - `VETTLY_API_KEY` - Your Vettly API key (required)
263
143
 
264
- ## License
144
+ ## Links
265
145
 
266
- MIT
146
+ - [vettly.dev](https://vettly.dev) - Sign up
147
+ - [docs.vettly.dev](https://docs.vettly.dev) - Documentation
148
+ - [Supabase Edge Functions](https://supabase.com/docs/guides/functions) - Supabase docs
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@vettly/supabase",
3
- "version": "0.1.0",
4
- "description": "Vettly content moderation for Supabase Edge Functions",
3
+ "version": "0.1.1",
4
+ "description": "Vettly decision infrastructure for Supabase Edge Functions. Deno-compatible, fetch-based client.",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
7
8
  "types": "./dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
@@ -21,25 +22,19 @@
21
22
  "dist",
22
23
  "README.md"
23
24
  ],
24
- "scripts": {
25
- "build": "tsup src/index.ts src/edge.ts --format esm,cjs --dts --clean",
26
- "test": "bun test",
27
- "prepublishOnly": "bun run build"
28
- },
29
25
  "keywords": [
26
+ "vettly",
30
27
  "supabase",
31
28
  "edge-functions",
32
29
  "deno",
33
- "content-moderation",
34
- "moderation",
35
- "vettly",
36
- "trust-safety"
30
+ "decision-infrastructure",
31
+ "policy-governance"
37
32
  ],
38
33
  "author": "Vettly",
39
34
  "license": "MIT",
40
35
  "repository": {
41
36
  "type": "git",
42
- "url": "https://github.com/brian-nextaura/vettly-docs.git",
37
+ "url": "https://github.com/nextauralabs/vettly-docs.git",
43
38
  "directory": "packages/supabase"
44
39
  },
45
40
  "homepage": "https://vettly.dev",
@@ -47,11 +42,6 @@
47
42
  "access": "public"
48
43
  },
49
44
  "bugs": {
50
- "url": "https://github.com/brian-nextaura/vettly-docs/issues"
51
- },
52
- "devDependencies": {
53
- "@types/bun": "latest",
54
- "tsup": "^8.0.0",
55
- "typescript": "^5"
45
+ "url": "https://github.com/nextauralabs/vettly-docs/issues"
56
46
  }
57
47
  }