[READ-ONLY] a fast, modern browser for the npm registry
at main 158 lines 4.6 kB view raw
1import './node-pty.d.ts' 2 3export interface ConnectorConfig { 4 port: number 5 host: string 6} 7 8export interface ConnectorSession { 9 token: string 10 connectedAt: number 11 npmUser: string | null 12 /** Base64 data URL of the user's avatar */ 13 avatar: string | null 14} 15 16export type OperationType = 17 | 'org:add-user' 18 | 'org:rm-user' 19 | 'org:set-role' 20 | 'team:create' 21 | 'team:destroy' 22 | 'team:add-user' 23 | 'team:rm-user' 24 | 'access:grant' 25 | 'access:revoke' 26 | 'owner:add' 27 | 'owner:rm' 28 | 'package:init' 29 30export type OperationStatus = 31 | 'pending' 32 | 'approved' 33 | 'running' 34 | 'completed' 35 | 'failed' 36 | 'cancelled' 37 38export interface OperationResult { 39 stdout: string 40 stderr: string 41 exitCode: number 42 /** True if the operation failed due to missing/invalid OTP */ 43 requiresOtp?: boolean 44 /** True if the operation failed due to authentication failure (not logged in or token expired) */ 45 authFailure?: boolean 46 /** URLs detected in the command output (stdout + stderr) */ 47 urls?: string[] 48} 49 50export interface PendingOperation { 51 id: string 52 type: OperationType 53 params: Record<string, string> 54 description: string 55 command: string 56 status: OperationStatus 57 createdAt: number 58 result?: OperationResult 59 /** ID of operation this depends on (must complete successfully first) */ 60 dependsOn?: string 61 /** Auth URL detected during interactive execution (set while operation is still running) */ 62 authUrl?: string 63} 64 65export interface ConnectorState { 66 session: ConnectorSession 67 operations: PendingOperation[] 68} 69 70export interface ApiResponse<T = unknown> { 71 success: boolean 72 data?: T 73 error?: string 74} 75 76// -- Connector API contract (shared by real + mock server) ------------------- 77 78export type OrgRole = 'developer' | 'admin' | 'owner' 79 80export type AccessPermission = 'read-only' | 'read-write' 81 82/** POST /connect response data */ 83export interface ConnectResponseData { 84 npmUser: string | null 85 avatar: string | null 86 connectedAt: number 87} 88 89/** GET /state response data */ 90export interface StateResponseData { 91 npmUser: string | null 92 avatar: string | null 93 operations: PendingOperation[] 94} 95 96/** POST /execute response data */ 97export interface ExecuteResponseData { 98 results: Array<{ id: string; result: OperationResult }> 99 otpRequired?: boolean 100 authFailure?: boolean 101 urls?: string[] 102} 103 104/** POST /approve-all response data */ 105export interface ApproveAllResponseData { 106 approved: number 107} 108 109/** DELETE /operations/all response data */ 110export interface ClearOperationsResponseData { 111 removed: number 112} 113 114/** Request body for POST /operations */ 115export interface CreateOperationBody { 116 type: OperationType 117 params: Record<string, string> 118 description: string 119 command: string 120 dependsOn?: string 121} 122 123/** 124 * Connector API endpoint contract. Both server.ts and mock-app.ts must 125 * conform to these shapes, enforced via `satisfies` and `AssertEndpointsImplemented`. 126 */ 127export interface ConnectorEndpoints { 128 'POST /connect': { body: { token: string }; data: ConnectResponseData } 129 'GET /state': { body: never; data: StateResponseData } 130 'POST /operations': { body: CreateOperationBody; data: PendingOperation } 131 'POST /operations/batch': { body: CreateOperationBody[]; data: PendingOperation[] } 132 'DELETE /operations': { body: never; data: void } 133 'DELETE /operations/all': { body: never; data: ClearOperationsResponseData } 134 'POST /approve': { body: never; data: PendingOperation } 135 'POST /approve-all': { body: never; data: ApproveAllResponseData } 136 'POST /retry': { body: never; data: PendingOperation } 137 'POST /execute': { 138 body: { otp?: string; interactive?: boolean; openUrls?: boolean } 139 data: ExecuteResponseData 140 } 141 'GET /org/:org/users': { body: never; data: Record<string, OrgRole> } 142 'GET /org/:org/teams': { body: never; data: string[] } 143 'GET /team/:scopeTeam/users': { body: never; data: string[] } 144 'GET /package/:pkg/collaborators': { body: never; data: Record<string, AccessPermission> } 145 'GET /user/packages': { body: never; data: Record<string, AccessPermission> } 146 'GET /user/orgs': { body: never; data: string[] } 147} 148 149/** Compile-time check that a server implements exactly the ConnectorEndpoints keys. */ 150type IsExact<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false 151export type AssertEndpointsImplemented<Implemented extends string> = 152 IsExact<Implemented, keyof ConnectorEndpoints> extends true 153 ? true 154 : { 155 error: 'Endpoint mismatch' 156 missing: Exclude<keyof ConnectorEndpoints, Implemented> 157 extra: Exclude<Implemented, keyof ConnectorEndpoints> 158 }