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

permissify

v1.1.3

Published

[![npm version](https://img.shields.io/npm/v/permissify.svg)](https://www.npmjs.com/package/permissify) [![License](https://img.shields.io/npm/l/permissify.svg)](LICENSE) [![Downloads](https://img.shields.io/npm/dt/permissify.svg)](https://www.npmjs.com

Readme

📦 Permissify

npm version License Downloads

Permissify is a wrapper for the navigator browser api. It greatly improves the developer experience by providing more detailed feedback.

Enjoy my work? :)

Buy me a coffee! ☕

✨ Features

  • 🚀 Works on all browsers

  • 🔥 Framework for convenient camera usage

  • ✅ Classes as Enums: strongly typed and usable with instanceof

  • 🔧 Strongly typed and amazing IntelliSense via discriminated unions(tagged unions)


Table of Contents

  1. Introduction
  2. Installation
  3. Usage
  4. API Reference
  5. Type Reference
  6. Examples
  7. Contributing
  8. Changelog
  9. Support
  10. License

📦 Installation

Install via npm:

   npm install permissify

Or using yarn:

   yarn add permissify

🚀 Usage

Basic example:

import { CameraPermissionHandler } from "permissify";

const handler = new CameraPermissionHandler();

onMounted(async () => {
    const initResult = await handler.initHandler();
    if(initResult.permissionGranted === true) {
        //request successful and results(strongly typed):
        const workingStream = initResult.request.result.stream;
        //set html stream source;
        console.log(initResult.request.result.devices);
        return;
    }
    //handle any kind of errors
})

More advanced example:

import { CameraPermissionHandler } from "permissify";
import { CameraInitErrorClass } from "permissify";

const handler = new CameraPermissionHandler();

onMounted(async () => {
    const initResult = await handler.initHandler();

    //Handle initial errors e.g Navigator api not supported
    if (initResult instanceof CameraInitErrorClass) {
        console.log("Error starting cam: ", initResult); //Handle your initial error
        return;
    }

    //IMPORTANT: strictly check for false (instead of !initResult.permissionGranted) 
    // to retain strong ts types and intelliSense
    if(initResult.permissionGranted === false) {
        console.log("Camera Access denied by: ", initResult.deniedBy); //Browser or User
        console.log("Is retryable: ", initResult.retryable); //handle retry
        return
    }

    //request successful and results(strongly typed):
    const workingStream = initResult.request.result.stream;
    //set html stream source;
    console.log(initResult.request.result.devices);
})

onUnmounted(() => {
    //stop camera
})

on(eventName: , listener: () => void): void

Requests permission for video device access and returns the result, including the permission state before and after the request.

This is considered to be the more "unguided approach" to request a videoDevice. Consider using startCamera() instead

Events:

| Name | callback-type | Description | |----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | video-devicelist-update | Map<string, MediaDeviceInfo> | Gets fired when the list of available video-devices changes. This can either happen when the list is first initalized or when the browser detects a new device/ a device is removed. | | log | string | Gets fired for internal logs. | | permission-status-change | { detail: string, state: BrowserPermissionStateClass } | Gets fired when the browser permission state changes. This could be the case when the user manually disables camera access in the browser. |

Parameters:

| Parameter | Type | Description | |-------------|-------------------------------------------------|------------------------| | eventName | [event-name] as string | The event to listen to | | listener | (data: [callback-type] of [event-name]) => void | The event to listen to |

Example:

import { CameraPermissionHandler } from "permissify";
import { BrowserPermissionStateClass } from "permissify";

const handler = new CameraPermissionHandler();
handler.on('permission-status-change', (data: { detail: string, state: BrowserPermissionStateClass }) => {
    console.log(data.state, data.detail)
   //handle data
})

Returns:

  • void

requestVideoDevice(userMediaConstraints?: MediaStreamConstraints): Promise<SuccessfulCameraRequest | FailedCameraRequest>

Requests permission for video device access and returns the result, including the permission state before and after the request.

This is considered to be the more "unguided approach" to request a videoDevice. Consider using startCamera() instead

Parameters:

| Parameter | Type | Description | |-----------------------|------------------------|----------------------------------------------------| | userMediaConstraints | MediaStreamConstraints | The constraints for accessing the media stream (optional) |

Returns:


getVideoDevices(): Promise<{ successful: true, result: MediaDeviceInfo[], duration: number } | { successful: false, result: string, duration: number }>

Gets a list of video devices and returns either a success with the device list or a failure with the error message.

Parameters:

None

Returns:

  • Promise<{ successful: true, result: MediaDeviceInfo[], duration: number } | { successful: false, result: string, duration: number }> - A promise that resolves with either a successful response containing video devices or a failed response with an error message.

getMediaDeviceByStream(stream: MediaStream)

Extracts the video device ID from the given media stream.

Parameters:

| Parameter | Type | Description | |-----------|------------|----------------------------------------| | stream | MediaStream | The media stream to extract device info from |

Returns:

  • { videoDevice: MediaTrackSettings | null } - The video device settings extracted from the media stream.

startCamera(id?: string, constraints?: MediaStreamConstraints): Promise<CameraRequestAcceptedWrapper | CameraRequestDeniedWrapper | CameraInitErrorClass>

Starts the camera with the given device ID and constraints, and returns the result based on permission state.

Parameters:

| Parameter | Type | Description | |-------------|------------------------|--------------------------------------------------| | id | string (optional) | The ID of the video device to use (optional) | | constraints | MediaStreamConstraints | The media stream constraints (optional) |

Returns:


getBrowserPermissionState(): Promise<{ state: BrowserPermissionStateClass, detail: string }>

Checks the current permission state for camera access and returns the state along with a detailed message.

Parameters:

None

Returns:

  • Promise<{ state: BrowserPermissionStateClass, detail: string }> - A promise that resolves with the camera permission state and a description of the state.

stopCameraByStream(stream: MediaStream, track?: MediaStreamTrack)

Stops the given media stream or a specific track within the stream.

Parameters:

| Parameter | Type | Description | |-----------|-----------------|---------------------------------------------------| | stream | MediaStream | The media stream to stop | | track | MediaStreamTrack (optional) | A specific track to remove from the stream (optional) |

Returns:

  • CameraInitErrorClass | void - Returns a CameraInitErrorClass if the camera ID doesn't exist, or stops the camera/ a specific track if provided.

stopCameraStreamById(cameraId: string, track?: MediaStreamTrack)

Stops the camera stream associated with the given camera ID, or stops a specific track in the stream.

Parameters:

| Parameter | Type | Description | |------------|---------------------|---------------------------------------------------| | cameraId | string | The ID of the camera stream to stop | | track | MediaStreamTrack (optional) | A specific track to remove from the stream (optional) |

Returns:

  • CameraInitErrorClass | void - Returns a CameraInitErrorClass if the camera ID doesn't exist, or stops the tracks in the stream.

getPreferredCamera(videoDevices: MediaDeviceInfo[])

Determines the preferred camera (environmental or front) from a list of available video devices.

Parameters:

| Parameter | Type | Description | |-------------------|-------------------|-------------------------------------------------------| | videoDevices | MediaDeviceInfo | An array of available video devices |

Returns:

  • { facing: string, id: string } - Returns the preferred camera's facing direction ('environment', 'front', or 'unknown') and the device ID of the camera.

initHandler(constraints: MediaStreamConstraints = { video: GlobalIdealCameraConstraints }): Promise<CameraRequestAcceptedWrapper | CameraRequestDeniedWrapper | CameraInitErrorClass>

Initializes the camera and handles permission states, device detection, and updates for the camera access.

Parameters:

| Parameter | Type | Description | |---------------|----------------------|---------------------------------------------------| | constraints | MediaStreamConstraints (optional) | The constraints for the media stream (default is GlobalIdealCameraConstraints) |

Returns:


📖 API Reference: Types

Resolution Table: resolution16By9Table

Defines a mapping of common resolutions with a 16:9 aspect ratio, including 4k and 720p resolutions.

{
  '4k': { height: 4096, width: 2160 },
  '720p': { height: 1280, width: 720 }
}

Global Camera Constraints: GlobalIdealCameraConstraints

Defines ideal camera settings using 720p resolution with a front-facing camera and a 60fps frame rate.

{
  height: { ideal: 1280 },
  width: { ideal: 720 },
  facingMode: { ideal: 'environment' },
  frameRate: { ideal: 60 }
}

FailedCameraRequest

Represents a failed camera request with details about permission state, error information, and request duration.


SuccessfulCameraRequestResult

Represents a successful camera request, containing the stream and device information.


SuccessfulCameraRequest

Represents a successful camera request, including permission states and the resulting stream and device information.


RequestRetryableBasic

Represents a request that can be retried, indicating if the retry is possible.


RequestRetryableAfterReload

Describes a retryable request that can only be retried after a reload, specifying the trigger for reload.


RequestRetryableUnknown

Describes a retryable request with an unknown status.

CameraRequestDeniedWrapper

Represents a denied camera request with details about the denial reason, retry status, and permission state.


CameraRequestAcceptedWrapper

Represents an accepted camera request with permission status and result details.


CameraInitErrorClass

Represents various camera initialization error states such as PermissionDismissed, PermissionDenied, NoDevices, etc.

class CameraInitErrorClass {
  static readonly PermissionDismissed = new CameraInitErrorClass("PermissionDismissed");
  static readonly PermissionDenied = new CameraInitErrorClass("PermissionDenied");
  static readonly InUse = new CameraInitErrorClass("InUse");
  static readonly Overconstrained = new CameraInitErrorClass("Overconstrained");
  static readonly UnknownError = new CameraInitErrorClass("UnknownError");
  static readonly BrowserApiInaccessible = new CameraInitErrorClass("BrowserApiInaccessible");
  static readonly NoDevices = new CameraInitErrorClass("NoDevices");
}

BrowserDeniedReasonClass

Represents the reason for denial of camera access, either by the browser or the user.

class BrowserDeniedReasonClass {
  static readonly Browser = new BrowserDeniedReasonClass("Browser");
  static readonly User = new BrowserDeniedReasonClass("User");
}

BrowserPermissionStateClass

Represents the permission state of the browser, with values like Granted, Denied, Prompt, etc.


export class PermissionsRetryableClass {
  static readonly Yes = new PermissionsRetryableClass("Yes");
  static readonly No = new PermissionsRetryableClass("No");
  static readonly AfterReload = new PermissionsRetryableClass("AfterReload");
  static readonly Unknown = new PermissionsRetryableClass("Unknown");
}

🎯 Examples

Check out the /examples folder for more detailed usage.


🛠️ Development

Clone the repository:

git clone https://github.com/Laurenz-M/permissify.git
cd permissify
npm install

📝 Changelog

  • Version 1.1.0: Change function names and add documentation

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature-branch)
  3. Commit your changes (git commit -m 'Add new feature')
  4. Push to the branch (git push origin feature-branch)
  5. Open a Pull Request

📜 License

This project is licensed under the MIT License - see the LICENSE file for details.


📬 Contact & Support