npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@peepl/proctoring-server

v0.1.0

Published

Server-side integration helpers for client-owned proctoring analysis

Readme

@peepl/proctoring-server

Node.js 20+ backend SDK for client-owned camera analysis. It validates model results and submits them directly to PEEPL using an API key. It does not run inference, load models, or access cameras.

Use @peepl/proctoring-browser on your client page to capture images and send them to your backend.

Install

bun add @peepl/proctoring-server

Registry installation requires the package to be published there. To build from source, see the workspace guide.

Backend integration

PEEPL must enable external camera analysis for your client and issue an API key. Keep that key and your AI credentials on your server.

Your route must authenticate and authorize the candidate, apply request limits and CSRF protection, and run inference on the received image. runClientModel below represents your own backend inference function, not an SDK method.

import { submitCameraAnalysis } from '@peepl/proctoring-server'
import type { CameraAnalysisRequest, CameraAnalysisResult } from '@peepl/proctoring-server'

async function analyzeAuthorizedImage(input: CameraAnalysisRequest) {
  const result: CameraAnalysisResult = await runClientModel(input.image)
  await submitCameraAnalysis({
    gatewayUrl: process.env.PEEPL_GATEWAY_URL!,
    apiKey: process.env.PEEPL_ANALYSIS_API_KEY!,
    request: {
      sid: input.sessionId,
      evidenceId: input.evidenceId,
      capturedAt: input.capturedAt,
      image: input.image,
    },
    result,
  })
  return { status: 'submitted' }
}

| Backend setting | Value | |---|---| | PEEPL_GATEWAY_URL | HTTPS gateway base URL supplied by PEEPL; retain a trailing slash when it includes a path prefix. | | PEEPL_ANALYSIS_API_KEY | API key issued for your client. |

The input is the browser request. Return { "status": "submitted" } as JSON only after submission succeeds. Propagate inference or submission failures as a non-success HTTP response. Never submit a detection result supplied by the browser.

Model result contract

Normalize your model's output into this shape:

{
  "model": "client-face-model",
  "width": 320,
  "height": 320,
  "faces": [
    {
      "box": { "x": 80, "y": 40, "w": 120, "h": 160 },
      "score": 0.95,
      "landmarks": {
        "left_eye": { "x": 110, "y": 85 },
        "right_eye": { "x": 160, "y": 85 },
        "nose": { "x": 135, "y": 110 },
        "mouth_left": { "x": 115, "y": 140 },
        "mouth_right": { "x": 155, "y": 140 }
      }
    }
  ]
}
  • width and height must match the submitted JPEG, not resized model input.
  • Coordinates use original-image pixels. Eye/mouth names are image-space: left_eye is the eye with the smaller x coordinate, not the person's left eye.
  • Boxes must stay within the image, with positive width and height.
  • Scores must be finite numbers from 0 to 1. Each face needs all five landmarks; landmarks outside the image can represent an incomplete face.
  • Return one entry per face, at most 10. No face is faces: [].
  • Inference failure is an error, not faces: [].

For external analysis, PEEPL records an incident unless there is exactly one face with score at least 0.7, all five landmarks inside the image, and a box more than 2 pixels from every edge.

AI compatibility

| AI implementation | Integration requirement | |---|---| | Existing nucleus-api-face-detector YuNet API | Use the successful response's data object. | | Client or vendor face-detection API | Adapt its output to the result contract above. | | ONNX/PyTorch/TensorFlow model | Run it in your backend runtime, then normalize its output. | | Text-only analysis or face count only | Insufficient: boxes, scores, and landmarks are required. |

The SDK is provider-agnostic, not an automatic model loader. It does not add identity matching, liveness detection, or screen/object analysis.

Submission requirements

  • The gateway verifies that the API key and candidate embed session belong to the same client, and validates the JPEG and analysis result.
  • capturedAt must be within five minutes of PEEPL's clock; synchronize your backend clock. Evidence IDs are deduplicated for 12 hours.
  • An API key authenticates your backend, not model accuracy or video authenticity.

Other backend languages can submit directly with POST {gateway}/embed/external-analysis, an x-api-key header, and a JSON body containing sid, evidence_id, captured_at, image, and analysis. analysis follows the model result contract above. The image must be a JPEG data URL. This package itself runs only on Node.js.

API

| Member | Description | |---|---| | submitCameraAnalysis({ gatewayUrl, apiKey, request, result, fetchImpl?, signal? }) | Validate and submit a result. Resolves on success; throws on validation or HTTP failure. | | validateCameraAnalysisResult(result) | Validate a model result without submitting. Throws if invalid. | | fetchImpl | Optional custom fetch implementation. | | signal | Optional abort signal for the submission request. |

TypeScript exports include CameraAnalysisRequest, CameraAnalysisResult, AnalysisFace, SubmitCameraAnalysisRequest, and SubmitCameraAnalysisOptions.