You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.8 KiB
121 lines
3.8 KiB
/**
|
|
* Zod schemas for strong structural validation
|
|
*/
|
|
|
|
import { z } from 'zod';
|
|
import { JWT_ID_PATTERN } from './constants';
|
|
|
|
// Core schemas
|
|
export const PlanSummarySchema = z.object({
|
|
jwtId: z.string().regex(JWT_ID_PATTERN, 'Invalid JWT ID format'),
|
|
handleId: z.string().min(1),
|
|
name: z.string().min(1),
|
|
description: z.string(),
|
|
issuerDid: z.string().startsWith('did:key:'),
|
|
agentDid: z.string().startsWith('did:key:'),
|
|
startTime: z.string().datetime(),
|
|
endTime: z.string().datetime(),
|
|
locLat: z.number().nullable().optional(),
|
|
locLon: z.number().nullable().optional(),
|
|
url: z.string().url().nullable().optional(),
|
|
version: z.string()
|
|
});
|
|
|
|
export const PreviousClaimSchema = z.object({
|
|
jwtId: z.string().regex(JWT_ID_PATTERN),
|
|
claimType: z.string(),
|
|
claimData: z.record(z.unknown()),
|
|
metadata: z.object({
|
|
createdAt: z.string().datetime(),
|
|
updatedAt: z.string().datetime()
|
|
})
|
|
});
|
|
|
|
export const PlanSummaryAndPreviousClaimSchema = z.object({
|
|
planSummary: PlanSummarySchema,
|
|
previousClaim: PreviousClaimSchema.optional()
|
|
});
|
|
|
|
export const StarredProjectsResponseSchema = z.object({
|
|
data: z.array(PlanSummaryAndPreviousClaimSchema),
|
|
hitLimit: z.boolean(),
|
|
pagination: z.object({
|
|
hasMore: z.boolean(),
|
|
nextAfterId: z.string().regex(JWT_ID_PATTERN).nullable()
|
|
})
|
|
});
|
|
|
|
export const StarredProjectsRequestSchema = z.object({
|
|
planIds: z.array(z.string()).min(1),
|
|
afterId: z.string().regex(JWT_ID_PATTERN).optional(),
|
|
beforeId: z.string().regex(JWT_ID_PATTERN).optional(),
|
|
limit: z.number().min(1).max(100).default(100)
|
|
});
|
|
|
|
// Deep link parameter validation
|
|
export const DeepLinkParamsSchema = z.object({
|
|
jwtIds: z.array(z.string().regex(JWT_ID_PATTERN)).max(10).optional(),
|
|
projectId: z.string().regex(/^[a-zA-Z0-9_-]+$/).optional(),
|
|
jwtId: z.string().regex(JWT_ID_PATTERN).optional(),
|
|
shortlink: z.string().min(1).optional()
|
|
}).refine(
|
|
(data) => data.jwtIds || data.jwtId || data.projectId || data.shortlink,
|
|
'At least one of jwtIds, jwtId, projectId, or shortlink must be provided'
|
|
);
|
|
|
|
// Error response schema
|
|
export const ErrorResponseSchema = z.object({
|
|
error: z.string(),
|
|
code: z.string().optional(),
|
|
message: z.string(),
|
|
details: z.record(z.unknown()).optional(),
|
|
retryAfter: z.number().optional(),
|
|
requestId: z.string().optional()
|
|
});
|
|
|
|
// Rate limit response schema
|
|
export const RateLimitResponseSchema = z.object({
|
|
error: z.literal('Rate limit exceeded'),
|
|
code: z.literal('RATE_LIMIT_EXCEEDED'),
|
|
message: z.string(),
|
|
details: z.object({
|
|
limit: z.number(),
|
|
window: z.string(),
|
|
resetAt: z.string().datetime(),
|
|
remaining: z.number().optional()
|
|
}),
|
|
retryAfter: z.number(),
|
|
requestId: z.string()
|
|
});
|
|
|
|
// Acknowledgment request schema
|
|
export const AcknowledgmentRequestSchema = z.object({
|
|
acknowledgedJwtIds: z.array(z.string().regex(JWT_ID_PATTERN)).min(1),
|
|
acknowledgedAt: z.string().datetime(),
|
|
clientVersion: z.string()
|
|
});
|
|
|
|
// Acknowledgment response schema
|
|
export const AcknowledgmentResponseSchema = z.object({
|
|
acknowledged: z.number(),
|
|
failed: z.number(),
|
|
alreadyAcknowledged: z.number(),
|
|
acknowledgmentId: z.string(),
|
|
timestamp: z.string().datetime()
|
|
});
|
|
|
|
// Clock sync response schema
|
|
export const ClockSyncResponseSchema = z.object({
|
|
serverTime: z.number(),
|
|
clientTime: z.number(),
|
|
offset: z.number(),
|
|
ntpServers: z.array(z.string()).optional()
|
|
});
|
|
|
|
// Type exports for use in host apps (only export types not already in types.ts)
|
|
export type DeepLinkParams = z.infer<typeof DeepLinkParamsSchema>;
|
|
export type ErrorResponse = z.infer<typeof ErrorResponseSchema>;
|
|
export type RateLimitResponse = z.infer<typeof RateLimitResponseSchema>;
|
|
export type AcknowledgmentRequest = z.infer<typeof AcknowledgmentRequestSchema>;
|
|
export type AcknowledgmentResponse = z.infer<typeof AcknowledgmentResponseSchema>;
|
|
export type ClockSyncResponse = z.infer<typeof ClockSyncResponseSchema>;
|
|
|