Spaces:
Running
Running
Download apps/api/src/network/network.router.ts from Benaah/MicProtocol: direct link, hf CLI and curl.
- Browser
- Download file 13.6 kB
-
https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/apps/api/src/network/network.router.ts
- Command line
-
hf download hf://spaces/Benaah/MicProtocol/apps/api/src/network/network.router.ts
-
curl -L -o network.router.ts https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/apps/api/src/network/network.router.ts
13.6 kB
| import { Injectable } from "@nestjs/common"; | |
| import { z } from "zod"; | |
| import { | |
| router, | |
| publicProcedure, | |
| protectedProcedure, | |
| adminPermissionProcedure, | |
| } from "../trpc/trpc.init"; | |
| import { NetworkService } from "./network.service"; | |
| import { TrustScoreEngine } from "./trust-score.service"; | |
| import { VerificationPipeline } from "./verification-pipeline.service"; | |
| import { | |
| AdminPermission, | |
| createGuestPublicProfileSchema, | |
| updateGuestPublicProfileSchema, | |
| guestNetworkSearchSchema, | |
| createNetworkBookingRequestSchema, | |
| respondToBookingRequestSchema, | |
| createNetworkBookmarkSchema, | |
| updateNetworkBookmarkSchema, | |
| createHostReviewSchema, | |
| trackProfileViewSchema, | |
| requestBadgeSchema, | |
| revokeBadgeSchema, | |
| getVerificationStatusSchema, | |
| getTrustScoreSchema, | |
| recomputeAllTrustScoresSchema, | |
| BookmarkStatus, | |
| ProfileViewSource, | |
| VerificationBadgeType, | |
| } from "@micprotocol/shared-types"; | |
| () | |
| export class NetworkRouter { | |
| constructor( | |
| private readonly networkService: NetworkService, | |
| private readonly trustScoreEngine: TrustScoreEngine, | |
| private readonly verificationPipeline: VerificationPipeline, | |
| ) {} | |
| get router() { | |
| return router({ | |
| // βββ Profile Management βββββββββββββββββββββββ | |
| createProfile: protectedProcedure | |
| .input(createGuestPublicProfileSchema) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.createProfile(ctx.userId!, input); | |
| }), | |
| updateProfile: protectedProcedure | |
| .input(updateGuestPublicProfileSchema) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.updateProfile(ctx.userId!, input); | |
| }), | |
| getMyProfile: protectedProcedure | |
| .query(async ({ ctx }) => { | |
| return this.networkService.getMyProfile(ctx.userId!); | |
| }), | |
| // Public profile by vanity URL | |
| getProfile: publicProcedure | |
| .input(z.object({ vanityUrl: z.string() })) | |
| .query(async ({ input }) => { | |
| return this.networkService.getProfileByVanityUrl(input.vanityUrl); | |
| }), | |
| getProfileById: publicProcedure | |
| .input(z.object({ id: z.string().uuid() })) | |
| .query(async ({ input }) => { | |
| return this.networkService.getProfileById(input.id); | |
| }), | |
| // βββ Discovery Search βββββββββββββββββββββββββ | |
| search: publicProcedure | |
| .input(guestNetworkSearchSchema) | |
| .query(async ({ input }) => { | |
| return this.networkService.searchProfiles(input); | |
| }), | |
| trending: publicProcedure | |
| .input( | |
| z.object({ | |
| region: z.string().optional(), | |
| limit: z.number().int().min(1).max(50).default(10), | |
| }) | |
| ) | |
| .query(async ({ input }) => { | |
| return this.networkService.getTrending(input.region, input.limit); | |
| }), | |
| // βββ Profile Views ββββββββββββββββββββββββββββ | |
| trackView: publicProcedure | |
| .input(trackProfileViewSchema) | |
| .mutation(async ({ input }) => { | |
| return this.networkService.trackView(input); | |
| }), | |
| getViewStats: protectedProcedure | |
| .input( | |
| z.object({ | |
| profileId: z.string().uuid(), | |
| days: z.number().int().min(1).max(365).default(30), | |
| }) | |
| ) | |
| .query(async ({ ctx, input }) => { | |
| return this.networkService.getProfileViewStats( | |
| ctx.userId!, | |
| input.profileId, | |
| input.days, | |
| ); | |
| }), | |
| // βββ Bookmarks ββββββββββββββββββββββββββββββββ | |
| bookmark: protectedProcedure | |
| .input(createNetworkBookmarkSchema) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.createBookmark(input, ctx.userId!); | |
| }), | |
| updateBookmark: protectedProcedure | |
| .input( | |
| z.object({ | |
| id: z.string().uuid(), | |
| data: updateNetworkBookmarkSchema, | |
| }) | |
| ) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.updateBookmark(ctx.userId!, input.id, input.data); | |
| }), | |
| removeBookmark: protectedProcedure | |
| .input(z.object({ id: z.string().uuid() })) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.removeBookmark(ctx.userId!, input.id); | |
| }), | |
| listBookmarks: protectedProcedure | |
| .input( | |
| z.object({ | |
| podcastId: z.string().uuid(), | |
| status: z.nativeEnum(BookmarkStatus).optional(), | |
| }) | |
| ) | |
| .query(async ({ ctx, input }) => { | |
| return this.networkService.listBookmarks( | |
| input.podcastId, | |
| ctx.userId!, | |
| input.status, | |
| ); | |
| }), | |
| // βββ Booking Requests βββββββββββββββββββββββββ | |
| createBookingRequest: protectedProcedure | |
| .input(createNetworkBookingRequestSchema) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.createBookingRequest(input, ctx.userId!); | |
| }), | |
| respondToBookingRequest: protectedProcedure | |
| .input(respondToBookingRequestSchema) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.respondToBookingRequest( | |
| input.requestId, | |
| ctx.userId!, | |
| input.status, | |
| ); | |
| }), | |
| listBookingRequests: protectedProcedure | |
| .input( | |
| z.object({ | |
| profileId: z.string().uuid(), | |
| status: z.string().optional(), | |
| }) | |
| ) | |
| .query(async ({ ctx, input }) => { | |
| return this.networkService.listBookingRequests( | |
| ctx.userId!, | |
| input.profileId, | |
| input.status, | |
| ); | |
| }), | |
| listSentBookingRequests: protectedProcedure | |
| .input( | |
| z.object({ | |
| podcastId: z.string().uuid(), | |
| status: z.string().optional(), | |
| }) | |
| ) | |
| .query(async ({ ctx, input }) => { | |
| return this.networkService.listSentBookingRequests( | |
| ctx.userId!, | |
| input.podcastId, | |
| input.status, | |
| ); | |
| }), | |
| // βββ Reviews ββββββββββββββββββββββββββββββββββ | |
| submitReview: protectedProcedure | |
| .input(createHostReviewSchema) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.submitReview(ctx.userId!, input); | |
| }), | |
| // βββ Reputation βββββββββββββββββββββββββββββββ | |
| getReputationInsights: protectedProcedure | |
| .input(z.object({ profileId: z.string().uuid() })) | |
| .query(async ({ ctx, input }) => { | |
| return this.networkService.getReputationInsights(ctx.userId!, input.profileId); | |
| }), | |
| recalculateReputation: protectedProcedure | |
| .input(z.object({ profileId: z.string().uuid() })) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.networkService.recalculateReputation(ctx.userId!, input.profileId); | |
| }), | |
| // βββ Recommendations ββββββββββββββββββββββββββ | |
| getRecommendations: protectedProcedure | |
| .input( | |
| z.object({ | |
| profileId: z.string().uuid(), | |
| limit: z.number().int().min(1).max(20).default(5), | |
| }) | |
| ) | |
| .query(async ({ ctx, input }) => { | |
| return this.networkService.getRecommendations( | |
| ctx.userId!, | |
| input.profileId, | |
| input.limit | |
| ); | |
| }), | |
| getProfileNetworkStats: protectedProcedure | |
| .input(z.object({ profileId: z.string().uuid() })) | |
| .query(async ({ ctx, input }) => { | |
| return this.networkService.getProfileNetworkStats(ctx.userId!, input.profileId); | |
| }), | |
| // βββ Podcast Network Stats ββββββββββββββββββββ | |
| stats: protectedProcedure | |
| .input(z.object({ podcastId: z.string().uuid() })) | |
| .query(async ({ ctx, input }) => { | |
| return this.networkService.getPodcastNetworkStats(input.podcastId, ctx.userId!); | |
| }), | |
| // βββ Admin ββββββββββββββββββββββββββββββββββββ | |
| verifyProfile: adminPermissionProcedure(AdminPermission.MODERATION_RESOLVE) | |
| .input( | |
| z.object({ | |
| profileId: z.string().uuid(), | |
| status: z.enum(["basic", "verified", "featured"]), | |
| }) | |
| ) | |
| .mutation(async ({ input, ctx }) => { | |
| // Defense in depth: verifyProfile() re-checks the caller inside the | |
| // service via assertPlatformAdmin. | |
| return this.networkService.verifyProfile( | |
| ctx.userId!, // Pass current user for authorization | |
| input.profileId, | |
| input.status, | |
| ); | |
| }), | |
| // βββ Trust Score βββββββββββββββββββββββββββββ | |
| getTrustScore: protectedProcedure | |
| .input(getTrustScoreSchema) | |
| .query(async ({ input }) => { | |
| return this.trustScoreEngine.getTrustScore(input.profileId); | |
| }), | |
| recomputeTrustScore: adminPermissionProcedure(AdminPermission.OPS_HEALTH) | |
| .input(z.object({ profileId: z.string().uuid() })) | |
| .mutation(async ({ input }) => { | |
| return this.trustScoreEngine.computeAndPersist(input.profileId); | |
| }), | |
| recomputeAllTrustScores: adminPermissionProcedure(AdminPermission.OPS_HEALTH) | |
| .input(recomputeAllTrustScoresSchema) | |
| .mutation(async () => { | |
| return this.trustScoreEngine.recomputeAll(); | |
| }), | |
| // βββ Verification Pipeline βββββββββββββββββββ | |
| requestBadge: protectedProcedure | |
| .input(requestBadgeSchema) | |
| .mutation(async ({ ctx, input }) => { | |
| return this.verificationPipeline.requestBadge({ | |
| profileId: input.profileId, | |
| badgeType: input.badgeType as any, | |
| evidence: input.evidence, | |
| adminUserId: input.badgeType === "identity" ? ctx.userId! : undefined, | |
| }); | |
| }), | |
| revokeBadge: adminPermissionProcedure(AdminPermission.MODERATION_TAKEDOWN) | |
| .input(revokeBadgeSchema) | |
| .mutation(async ({ ctx, input }) => { | |
| // Defense in depth: revokeBadge() re-checks the caller inside the | |
| // service via assertPlatformAdmin. | |
| return this.verificationPipeline.revokeBadge( | |
| ctx.userId!, | |
| input.profileId, | |
| input.badgeType as any, | |
| ); | |
| }), | |
| getVerificationStatus: protectedProcedure | |
| .input(getVerificationStatusSchema) | |
| .query(async ({ input }) => { | |
| return this.verificationPipeline.getVerificationStatus(input.profileId); | |
| }), | |
| // Grants verification badges β a moderation decision surface (and it | |
| // targets arbitrary profileIds), so it requires MODERATION_RESOLVE. | |
| autoVerifyBadges: adminPermissionProcedure(AdminPermission.MODERATION_RESOLVE) | |
| .input(z.object({ profileId: z.string().uuid() })) | |
| .mutation(async ({ input }) => { | |
| return this.verificationPipeline.autoVerifyEligibleBadges(input.profileId); | |
| }), | |
| // βββ Network Health ββββββββββββββββββββββββββ | |
| getNetworkHealth: adminPermissionProcedure(AdminPermission.OPS_READ).query(async () => { | |
| return this.networkService.getNetworkHealth(); | |
| }), | |
| }); | |
| } | |
| } |