@vettly/shared 0.1.9

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/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # @nextauralabs/vettly-shared
2
+
3
+ Shared TypeScript types for the Vettly SDK ecosystem.
4
+
5
+ ## Vettly Packages
6
+
7
+ | Package | Description |
8
+ |---------|-------------|
9
+ | [@nextauralabs/vettly-sdk](https://npmjs.com/package/@nextauralabs/vettly-sdk) | Core TypeScript SDK |
10
+ | [@nextauralabs/vettly-react](https://npmjs.com/package/@nextauralabs/vettly-react) | React components |
11
+ | [@nextauralabs/vettly-express](https://npmjs.com/package/@nextauralabs/vettly-express) | Express middleware |
12
+ | [@nextauralabs/vettly-nextjs](https://npmjs.com/package/@nextauralabs/vettly-nextjs) | Next.js integration |
13
+
14
+ ## Usage
15
+
16
+ ```typescript
17
+ import type {
18
+ CheckRequest,
19
+ CheckResponse,
20
+ Policy,
21
+ Category,
22
+ Action
23
+ } from '@nextauralabs/vettly-shared'
24
+ ```
25
+
26
+ ## Links
27
+
28
+ - [vettly.dev](https://vettly.dev) - Sign up
29
+ - [docs.vettly.dev](https://docs.vettly.dev) - Documentation
package/dist/index.cjs ADDED
@@ -0,0 +1,362 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ActionSchema: () => ActionSchema,
34
+ CategorySchema: () => CategorySchema,
35
+ CheckRequestSchema: () => CheckRequestSchema,
36
+ CheckResponseSchema: () => CheckResponseSchema,
37
+ ContentItemResultSchema: () => ContentItemResultSchema,
38
+ ContentTypeSchema: () => ContentTypeSchema,
39
+ DecisionSchema: () => DecisionSchema,
40
+ FallbackConfigSchema: () => FallbackConfigSchema,
41
+ ModerationError: () => ModerationError,
42
+ MultiModalCheckRequestSchema: () => MultiModalCheckRequestSchema,
43
+ MultiModalCheckResponseSchema: () => MultiModalCheckResponseSchema,
44
+ OverrideSchema: () => OverrideSchema,
45
+ PolicySchema: () => PolicySchema,
46
+ PolicyValidationError: () => PolicyValidationError,
47
+ ProviderError: () => ProviderError,
48
+ ProviderNameSchema: () => ProviderNameSchema,
49
+ ReplayRequestSchema: () => ReplayRequestSchema,
50
+ RuleSchema: () => RuleSchema,
51
+ UseCaseTypeSchema: () => UseCaseTypeSchema,
52
+ WebhookEndpointSchema: () => WebhookEndpointSchema,
53
+ WebhookEventTypeSchema: () => WebhookEventTypeSchema,
54
+ calculatePolicyVersion: () => calculatePolicyVersion,
55
+ formatCost: () => formatCost,
56
+ formatLatency: () => formatLatency,
57
+ generateRequestId: () => generateRequestId,
58
+ generateUUID: () => generateUUID,
59
+ hashContent: () => hashContent
60
+ });
61
+ module.exports = __toCommonJS(index_exports);
62
+
63
+ // src/types.ts
64
+ var import_zod = require("zod");
65
+ var ContentTypeSchema = import_zod.z.enum(["text", "image", "video"]);
66
+ var UseCaseTypeSchema = import_zod.z.enum([
67
+ "social_post",
68
+ "comment",
69
+ "profile",
70
+ "message",
71
+ "review",
72
+ "listing",
73
+ "bio",
74
+ "other"
75
+ ]);
76
+ var CategorySchema = import_zod.z.enum([
77
+ "hate_speech",
78
+ "harassment",
79
+ "violence",
80
+ "self_harm",
81
+ "sexual",
82
+ "spam",
83
+ "profanity",
84
+ "scam",
85
+ "illegal"
86
+ ]);
87
+ var ProviderNameSchema = import_zod.z.enum([
88
+ "openai",
89
+ "perspective",
90
+ "hive",
91
+ "azure",
92
+ "bot_detection",
93
+ "gemini_vision",
94
+ "mock",
95
+ "fallback"
96
+ ]);
97
+ var ActionSchema = import_zod.z.enum(["block", "warn", "flag", "allow"]);
98
+ var RuleSchema = import_zod.z.object({
99
+ category: CategorySchema,
100
+ threshold: import_zod.z.number().min(0).max(1),
101
+ provider: ProviderNameSchema,
102
+ action: ActionSchema,
103
+ priority: import_zod.z.number().optional().default(0),
104
+ // Custom prompt-based moderation (Pro+ tier only)
105
+ // When set, uses Gemini Vision for semantic image analysis
106
+ customPrompt: import_zod.z.string().min(1).max(500).optional(),
107
+ customCategory: import_zod.z.string().min(1).max(100).optional()
108
+ }).refine(
109
+ (data) => {
110
+ const hasPrompt = !!data.customPrompt;
111
+ const hasCategory = !!data.customCategory;
112
+ return hasPrompt === hasCategory;
113
+ },
114
+ {
115
+ message: "customPrompt and customCategory must both be set, or both be omitted",
116
+ path: ["customPrompt"]
117
+ }
118
+ );
119
+ var OverrideSchema = import_zod.z.object({
120
+ locale: import_zod.z.string().optional(),
121
+ region: import_zod.z.string().optional(),
122
+ data_residency: import_zod.z.string().optional(),
123
+ provider: ProviderNameSchema.optional()
124
+ });
125
+ var FallbackConfigSchema = import_zod.z.object({
126
+ provider: ProviderNameSchema,
127
+ on_timeout: import_zod.z.boolean().optional().default(true),
128
+ timeout_ms: import_zod.z.number().optional().default(5e3)
129
+ });
130
+ var PolicySchema = import_zod.z.object({
131
+ name: import_zod.z.string(),
132
+ version: import_zod.z.string(),
133
+ rules: import_zod.z.array(RuleSchema),
134
+ overrides: import_zod.z.array(OverrideSchema).optional(),
135
+ fallback: FallbackConfigSchema.optional()
136
+ });
137
+ var DecisionSchema = import_zod.z.object({
138
+ id: import_zod.z.string().uuid(),
139
+ content: import_zod.z.string(),
140
+ contentHash: import_zod.z.string(),
141
+ contentType: ContentTypeSchema,
142
+ policy: import_zod.z.object({
143
+ id: import_zod.z.string(),
144
+ version: import_zod.z.string()
145
+ }),
146
+ result: import_zod.z.object({
147
+ safe: import_zod.z.boolean(),
148
+ flagged: import_zod.z.boolean(),
149
+ action: ActionSchema,
150
+ categories: import_zod.z.array(
151
+ import_zod.z.object({
152
+ category: CategorySchema,
153
+ score: import_zod.z.number(),
154
+ threshold: import_zod.z.number(),
155
+ triggered: import_zod.z.boolean()
156
+ })
157
+ )
158
+ }),
159
+ provider: import_zod.z.object({
160
+ name: ProviderNameSchema,
161
+ latency: import_zod.z.number(),
162
+ cost: import_zod.z.number()
163
+ }),
164
+ metadata: import_zod.z.record(import_zod.z.unknown()).optional(),
165
+ timestamp: import_zod.z.string().datetime(),
166
+ requestId: import_zod.z.string().optional()
167
+ });
168
+ var MultiModalCheckRequestSchema = import_zod.z.object({
169
+ // Multi-modal content inputs
170
+ text: import_zod.z.string().max(1e5, "Text exceeds maximum size of 100KB").optional(),
171
+ images: import_zod.z.array(
172
+ import_zod.z.string().refine(
173
+ (val) => {
174
+ return val.startsWith("http://") || val.startsWith("https://") || val.startsWith("data:image/");
175
+ },
176
+ { message: "Images must be URLs or base64 data URIs" }
177
+ )
178
+ ).max(10, "Maximum 10 images per request").optional(),
179
+ video: import_zod.z.string().url("Video must be a valid URL").optional(),
180
+ // Moderation context
181
+ context: import_zod.z.object({
182
+ useCase: UseCaseTypeSchema.default("other"),
183
+ userId: import_zod.z.string().optional(),
184
+ userReputation: import_zod.z.number().min(0).max(1).optional(),
185
+ // 0-1 score
186
+ locale: import_zod.z.string().optional(),
187
+ region: import_zod.z.string().optional()
188
+ }).optional(),
189
+ // Policy and metadata
190
+ policyId: import_zod.z.string(),
191
+ metadata: import_zod.z.record(import_zod.z.unknown()).optional(),
192
+ requestId: import_zod.z.string().optional()
193
+ // For idempotency
194
+ }).refine(
195
+ (data) => {
196
+ return data.text || data.images?.length || data.video;
197
+ },
198
+ { message: "At least one of text, images, or video must be provided" }
199
+ );
200
+ var CheckRequestSchema = import_zod.z.object({
201
+ content: import_zod.z.string().min(1).max(1e5, "Content exceeds maximum size of 100KB"),
202
+ policyId: import_zod.z.string(),
203
+ contentType: ContentTypeSchema.optional().default("text"),
204
+ metadata: import_zod.z.record(import_zod.z.unknown()).optional(),
205
+ requestId: import_zod.z.string().optional()
206
+ // For idempotency
207
+ });
208
+ var ContentItemResultSchema = import_zod.z.object({
209
+ contentType: ContentTypeSchema,
210
+ contentRef: import_zod.z.string().optional(),
211
+ // URL or identifier for images/video
212
+ contentItemId: import_zod.z.string().uuid().optional(),
213
+ // Database ID for linking evidence
214
+ safe: import_zod.z.boolean(),
215
+ flagged: import_zod.z.boolean(),
216
+ action: ActionSchema,
217
+ categories: import_zod.z.array(
218
+ import_zod.z.object({
219
+ category: CategorySchema,
220
+ score: import_zod.z.number(),
221
+ triggered: import_zod.z.boolean()
222
+ })
223
+ ),
224
+ provider: ProviderNameSchema,
225
+ latency: import_zod.z.number(),
226
+ cost: import_zod.z.number(),
227
+ evidence: import_zod.z.object({
228
+ url: import_zod.z.string().url().optional(),
229
+ // Signed URL to evidence (screenshot, frame)
230
+ expiresAt: import_zod.z.string().datetime().optional()
231
+ }).optional()
232
+ });
233
+ var MultiModalCheckResponseSchema = import_zod.z.object({
234
+ decisionId: import_zod.z.string().uuid(),
235
+ safe: import_zod.z.boolean(),
236
+ // Overall safe if ALL content items are safe
237
+ flagged: import_zod.z.boolean(),
238
+ // Overall flagged if ANY content item is flagged
239
+ action: ActionSchema,
240
+ // Most severe action across all content
241
+ results: import_zod.z.array(ContentItemResultSchema),
242
+ // Per-content-type results
243
+ totalLatency: import_zod.z.number(),
244
+ totalCost: import_zod.z.number(),
245
+ requestId: import_zod.z.string().optional()
246
+ });
247
+ var CheckResponseSchema = import_zod.z.object({
248
+ decisionId: import_zod.z.string().uuid(),
249
+ safe: import_zod.z.boolean(),
250
+ flagged: import_zod.z.boolean(),
251
+ action: ActionSchema,
252
+ categories: import_zod.z.array(
253
+ import_zod.z.object({
254
+ category: CategorySchema,
255
+ score: import_zod.z.number(),
256
+ triggered: import_zod.z.boolean()
257
+ })
258
+ ),
259
+ provider: ProviderNameSchema,
260
+ latency: import_zod.z.number(),
261
+ cost: import_zod.z.number(),
262
+ requestId: import_zod.z.string().optional()
263
+ });
264
+ var ReplayRequestSchema = import_zod.z.object({
265
+ decisionId: import_zod.z.string().uuid(),
266
+ policyId: import_zod.z.string()
267
+ });
268
+ var ModerationError = class extends Error {
269
+ constructor(message, code, statusCode = 500, details) {
270
+ super(message);
271
+ this.code = code;
272
+ this.statusCode = statusCode;
273
+ this.details = details;
274
+ this.name = "ModerationError";
275
+ }
276
+ };
277
+ var PolicyValidationError = class extends ModerationError {
278
+ constructor(message, details) {
279
+ super(message, "POLICY_VALIDATION_ERROR", 400, details);
280
+ this.name = "PolicyValidationError";
281
+ }
282
+ };
283
+ var ProviderError = class extends ModerationError {
284
+ constructor(message, provider, details) {
285
+ super(message, "PROVIDER_ERROR", 502, { provider, ...details });
286
+ this.name = "ProviderError";
287
+ }
288
+ };
289
+ var WebhookEventTypeSchema = import_zod.z.enum([
290
+ "decision.created",
291
+ "decision.flagged",
292
+ "decision.blocked",
293
+ "policy.created",
294
+ "policy.updated"
295
+ ]);
296
+ var WebhookEndpointSchema = import_zod.z.object({
297
+ url: import_zod.z.string().url().refine(
298
+ (url) => {
299
+ if (process.env.NODE_ENV === "production") {
300
+ return !url.includes("localhost") && !url.includes("127.0.0.1");
301
+ }
302
+ return true;
303
+ },
304
+ "Localhost webhooks are not allowed in production"
305
+ ),
306
+ events: import_zod.z.array(WebhookEventTypeSchema),
307
+ description: import_zod.z.string().max(500).optional()
308
+ });
309
+
310
+ // src/utils.ts
311
+ var import_crypto = __toESM(require("crypto"), 1);
312
+ function hashContent(content) {
313
+ return import_crypto.default.createHash("sha256").update(content).digest("hex");
314
+ }
315
+ function generateUUID() {
316
+ return import_crypto.default.randomUUID();
317
+ }
318
+ function generateRequestId() {
319
+ return `req_${Date.now()}_${Math.random().toString(36).substring(7)}`;
320
+ }
321
+ function calculatePolicyVersion(yaml) {
322
+ return hashContent(yaml).substring(0, 16);
323
+ }
324
+ function formatCost(cost) {
325
+ return `$${cost.toFixed(6)}`;
326
+ }
327
+ function formatLatency(ms) {
328
+ if (ms < 1e3) {
329
+ return `${ms.toFixed(0)}ms`;
330
+ }
331
+ return `${(ms / 1e3).toFixed(2)}s`;
332
+ }
333
+ // Annotate the CommonJS export names for ESM import in node:
334
+ 0 && (module.exports = {
335
+ ActionSchema,
336
+ CategorySchema,
337
+ CheckRequestSchema,
338
+ CheckResponseSchema,
339
+ ContentItemResultSchema,
340
+ ContentTypeSchema,
341
+ DecisionSchema,
342
+ FallbackConfigSchema,
343
+ ModerationError,
344
+ MultiModalCheckRequestSchema,
345
+ MultiModalCheckResponseSchema,
346
+ OverrideSchema,
347
+ PolicySchema,
348
+ PolicyValidationError,
349
+ ProviderError,
350
+ ProviderNameSchema,
351
+ ReplayRequestSchema,
352
+ RuleSchema,
353
+ UseCaseTypeSchema,
354
+ WebhookEndpointSchema,
355
+ WebhookEventTypeSchema,
356
+ calculatePolicyVersion,
357
+ formatCost,
358
+ formatLatency,
359
+ generateRequestId,
360
+ generateUUID,
361
+ hashContent
362
+ });