Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

expo-file-system

Package Overview
Dependencies
Maintainers
27
Versions
138
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

expo-file-system - npm Package Compare versions

Comparing version 11.1.3 to 12.0.0

android/src/main/java/expo/modules/filesystem/CountingRequestBody.kt

2

build/ExponentFileSystem.js

@@ -1,2 +0,2 @@

import { NativeModulesProxy } from '@unimodules/core';
import { NativeModulesProxy } from 'expo-modules-core';
import ExponentFileSystemShim from './ExponentFileSystemShim';

@@ -3,0 +3,0 @@ let platformModule;

@@ -1,4 +0,3 @@

import { EventEmitter, Subscription } from '@unimodules/core';
import { DownloadOptions, DownloadPauseState, DownloadProgressCallback, DownloadProgressData, DownloadResult, EncodingType, FileInfo, FileSystemAcceptedUploadHttpMethod, FileSystemDownloadResult, FileSystemRequestDirectoryPermissionsResult, FileSystemSessionType, FileSystemUploadOptions, FileSystemUploadResult, FileSystemUploadType, ProgressEvent, ReadingOptions, WritingOptions } from './FileSystem.types';
export { DownloadOptions, DownloadPauseState, DownloadProgressCallback, DownloadProgressData, DownloadResult, EncodingType, FileInfo, FileSystemDownloadResult, FileSystemRequestDirectoryPermissionsResult, FileSystemAcceptedUploadHttpMethod, FileSystemSessionType, FileSystemUploadOptions, FileSystemUploadResult, FileSystemUploadType, ProgressEvent, ReadingOptions, WritingOptions, };
import { DownloadOptions, DownloadPauseState, DownloadProgressCallback, FileSystemNetworkTaskProgressCallback, DownloadProgressData, UploadProgressData, DownloadResult, EncodingType, FileInfo, FileSystemAcceptedUploadHttpMethod, FileSystemDownloadResult, FileSystemRequestDirectoryPermissionsResult, FileSystemSessionType, FileSystemUploadOptions, FileSystemUploadResult, FileSystemUploadType, ReadingOptions, WritingOptions } from './FileSystem.types';
export { DownloadOptions, DownloadPauseState, DownloadProgressCallback, DownloadProgressData, DownloadResult, EncodingType, FileInfo, FileSystemDownloadResult, FileSystemRequestDirectoryPermissionsResult, FileSystemAcceptedUploadHttpMethod, FileSystemSessionType, FileSystemUploadOptions, FileSystemUploadResult, FileSystemUploadType, FileSystemNetworkTaskProgressCallback, ReadingOptions, WritingOptions, };
export declare const documentDirectory: string | null;

@@ -34,13 +33,37 @@ export declare const cacheDirectory: string | null;

export declare function uploadAsync(url: string, fileUri: string, options?: FileSystemUploadOptions): Promise<FileSystemUploadResult>;
export declare function createDownloadResumable(uri: string, fileUri: string, options?: DownloadOptions, callback?: DownloadProgressCallback, resumeData?: string): DownloadResumable;
export declare class DownloadResumable {
_uuid: string;
_url: string;
_fileUri: string;
_options: DownloadOptions;
_resumeData?: string;
_callback?: DownloadProgressCallback;
_subscription?: Subscription | null;
_emitter: EventEmitter;
constructor(url: string, fileUri: string, options?: DownloadOptions, callback?: DownloadProgressCallback, resumeData?: string);
export declare function createDownloadResumable(uri: string, fileUri: string, options?: DownloadOptions, callback?: FileSystemNetworkTaskProgressCallback<DownloadProgressData>, resumeData?: string): DownloadResumable;
export declare function createUploadTask(url: string, fileUri: string, options?: FileSystemUploadOptions, callback?: FileSystemNetworkTaskProgressCallback<UploadProgressData>): UploadTask;
export declare abstract class FileSystemCancellableNetworkTask<T extends DownloadProgressData | UploadProgressData> {
private _uuid;
protected taskWasCanceled: boolean;
private emitter;
private subscription?;
cancelAsync(): Promise<void>;
protected isTaskCancelled(): boolean;
protected get uuid(): string;
protected abstract getEventName(): string;
protected abstract getCallback(): FileSystemNetworkTaskProgressCallback<T> | undefined;
protected addSubscription(): void;
protected removeSubscription(): void;
}
export declare class UploadTask extends FileSystemCancellableNetworkTask<UploadProgressData> {
private url;
private fileUri;
private callback?;
private options;
constructor(url: string, fileUri: string, options?: FileSystemUploadOptions, callback?: FileSystemNetworkTaskProgressCallback<UploadProgressData> | undefined);
protected getEventName(): string;
protected getCallback(): FileSystemNetworkTaskProgressCallback<UploadProgressData> | undefined;
uploadAsync(): Promise<FileSystemUploadResult | undefined>;
}
export declare class DownloadResumable extends FileSystemCancellableNetworkTask<DownloadProgressData> {
private url;
private _fileUri;
private options;
private callback?;
private resumeData?;
constructor(url: string, _fileUri: string, options?: DownloadOptions, callback?: FileSystemNetworkTaskProgressCallback<DownloadProgressData> | undefined, resumeData?: string | undefined);
get fileUri(): string;
protected getEventName(): string;
protected getCallback(): FileSystemNetworkTaskProgressCallback<DownloadProgressData> | undefined;
downloadAsync(): Promise<FileSystemDownloadResult | undefined>;

@@ -50,4 +73,2 @@ pauseAsync(): Promise<DownloadPauseState>;

savable(): DownloadPauseState;
_addSubscription(): void;
_removeSubscription(): void;
}

@@ -54,0 +75,0 @@ /**

@@ -1,2 +0,2 @@

import { EventEmitter, UnavailabilityError } from '@unimodules/core';
import { EventEmitter, UnavailabilityError } from 'expo-modules-core';
import { Platform } from 'react-native';

@@ -124,13 +124,110 @@ import { v4 as uuidv4 } from 'uuid';

}
export class DownloadResumable {
constructor(url, fileUri, options = {}, callback, resumeData) {
this._uuid = uuidv4();
this._url = url;
this._fileUri = fileUri;
this._options = options;
this._resumeData = resumeData;
this._callback = callback;
this._subscription = null;
this._emitter = new EventEmitter(ExponentFileSystem);
export function createUploadTask(url, fileUri, options, callback) {
return new UploadTask(url, fileUri, options, callback);
}
export class FileSystemCancellableNetworkTask {
_uuid = uuidv4();
taskWasCanceled = false;
emitter = new EventEmitter(ExponentFileSystem);
subscription;
async cancelAsync() {
if (!ExponentFileSystem.networkTaskCancelAsync) {
throw new UnavailabilityError('expo-file-system', 'networkTaskCancelAsync');
}
this.removeSubscription();
this.taskWasCanceled = true;
return await ExponentFileSystem.networkTaskCancelAsync(this.uuid);
}
isTaskCancelled() {
if (this.taskWasCanceled) {
console.warn('This task was already canceled.');
return true;
}
return false;
}
get uuid() {
return this._uuid;
}
addSubscription() {
if (this.subscription) {
return;
}
this.subscription = this.emitter.addListener(this.getEventName(), (event) => {
if (event.uuid === this.uuid) {
const callback = this.getCallback();
if (callback) {
callback(event.data);
}
}
});
}
removeSubscription() {
if (!this.subscription) {
return;
}
this.emitter.removeSubscription(this.subscription);
this.subscription = null;
}
}
export class UploadTask extends FileSystemCancellableNetworkTask {
url;
fileUri;
callback;
options;
constructor(url, fileUri, options, callback) {
super();
this.url = url;
this.fileUri = fileUri;
this.callback = callback;
const httpMethod = (options?.httpMethod?.toUpperCase ||
'POST');
this.options = {
sessionType: FileSystemSessionType.BACKGROUND,
uploadType: FileSystemUploadType.BINARY_CONTENT,
...options,
httpMethod,
};
}
getEventName() {
return 'expo-file-system.uploadProgress';
}
getCallback() {
return this.callback;
}
async uploadAsync() {
if (!ExponentFileSystem.uploadTaskStartAsync) {
throw new UnavailabilityError('expo-file-system', 'uploadTaskStartAsync');
}
if (this.isTaskCancelled()) {
return;
}
this.addSubscription();
const result = await ExponentFileSystem.uploadTaskStartAsync(this.url, this.fileUri, this.uuid, this.options);
this.removeSubscription();
return result;
}
}
export class DownloadResumable extends FileSystemCancellableNetworkTask {
url;
_fileUri;
options;
callback;
resumeData;
constructor(url, _fileUri, options = {}, callback, resumeData) {
super();
this.url = url;
this._fileUri = _fileUri;
this.options = options;
this.callback = callback;
this.resumeData = resumeData;
}
get fileUri() {
return this._fileUri;
}
getEventName() {
return 'expo-file-system.downloadProgress';
}
getCallback() {
return this.callback;
}
async downloadAsync() {

@@ -140,4 +237,7 @@ if (!ExponentFileSystem.downloadResumableStartAsync) {

}
this._addSubscription();
return await ExponentFileSystem.downloadResumableStartAsync(this._url, this._fileUri, this._uuid, this._options, this._resumeData);
if (this.isTaskCancelled()) {
return;
}
this.addSubscription();
return await ExponentFileSystem.downloadResumableStartAsync(this.url, this._fileUri, this.uuid, this.options, this.resumeData);
}

@@ -148,6 +248,13 @@ async pauseAsync() {

}
const pauseResult = await ExponentFileSystem.downloadResumablePauseAsync(this._uuid);
this._removeSubscription();
if (this.isTaskCancelled()) {
return {
fileUri: this._fileUri,
options: this.options,
url: this.url,
};
}
const pauseResult = await ExponentFileSystem.downloadResumablePauseAsync(this.uuid);
this.removeSubscription();
if (pauseResult) {
this._resumeData = pauseResult.resumeData;
this.resumeData = pauseResult.resumeData;
return this.savable();

@@ -163,33 +270,16 @@ }

}
this._addSubscription();
return await ExponentFileSystem.downloadResumableStartAsync(this._url, this._fileUri, this._uuid, this._options, this._resumeData);
if (this.isTaskCancelled()) {
return;
}
this.addSubscription();
return await ExponentFileSystem.downloadResumableStartAsync(this.url, this.fileUri, this.uuid, this.options, this.resumeData);
}
savable() {
return {
url: this._url,
fileUri: this._fileUri,
options: this._options,
resumeData: this._resumeData,
url: this.url,
fileUri: this.fileUri,
options: this.options,
resumeData: this.resumeData,
};
}
_addSubscription() {
if (this._subscription) {
return;
}
this._subscription = this._emitter.addListener('expo-file-system.downloadProgress', (event) => {
if (event.uuid === this._uuid) {
const callback = this._callback;
if (callback) {
callback(event.data);
}
}
});
}
_removeSubscription() {
if (!this._subscription) {
return;
}
this._emitter.removeSubscription(this._subscription);
this._subscription = null;
}
}

@@ -196,0 +286,0 @@ const baseReadAsStringAsync = readAsStringAsync;

@@ -43,3 +43,7 @@ export declare enum FileSystemSessionType {

};
export declare type DownloadProgressCallback = (data: DownloadProgressData) => void;
export declare type FileSystemNetworkTaskProgressCallback<T extends DownloadProgressData | UploadProgressData> = (data: T) => void;
/**
* @deprecated use `NetworkTaskProgressCallback<DownloadProgressData>` instead
*/
export declare type DownloadProgressCallback = FileSystemNetworkTaskProgressCallback<DownloadProgressData>;
export declare type DownloadProgressData = {

@@ -49,2 +53,6 @@ totalBytesWritten: number;

};
export declare type UploadProgressData = {
totalByteSent: number;
totalBytesExpectedToSend: number;
};
export declare type DownloadPauseState = {

@@ -84,8 +92,5 @@ url: string;

};
export declare type ProgressEvent = {
export declare type ProgressEvent<T> = {
uuid: string;
data: {
totalBytesWritten: number;
totalBytesExpectedToWrite: number;
};
data: T;
};

@@ -124,2 +129,4 @@ export declare type FileSystemRequestDirectoryPermissionsResult = {

readonly createSAFFileAsync?: PlatformMethod;
readonly networkTaskCancelAsync?: PlatformMethod;
readonly uploadTaskStartAsync?: PlatformMethod;
startObserving?: () => void;

@@ -126,0 +133,0 @@ stopObserving?: () => void;

@@ -13,8 +13,4 @@ # Changelog

## 11.1.3 — 2021-06-24
## 12.0.0 — 2021-09-08
_This version does not introduce any user-facing changes._
## 11.1.2 — 2021-06-24
### 🛠 Breaking changes

@@ -24,5 +20,5 @@

## 11.1.1 — 2021-06-22
### 💡 Others
_This version does not introduce any user-facing changes._
- Migrated from `@unimodules/core` to `expo-modules-core`. ([#13749](https://github.com/expo/expo/pull/13749) by [@tsapeta](https://github.com/tsapeta))

@@ -29,0 +25,0 @@ ## 11.1.0 — 2021-06-16

{
"name": "expo-file-system",
"version": "11.1.3",
"version": "12.0.0",
"description": "Provides access to the local file system on the device.",

@@ -33,3 +33,3 @@ "main": "build/index.js",

"license": "MIT",
"homepage": "https://docs.expo.io/versions/latest/sdk/filesystem/",
"homepage": "https://docs.expo.dev/versions/latest/sdk/filesystem/",
"jest": {

@@ -40,3 +40,3 @@ "preset": "expo-module-scripts"

"@expo/config-plugins": "^3.0.0",
"expo-modules-core": "~0.2.0",
"expo-modules-core": "~0.3.0",
"uuid": "^3.4.0"

@@ -48,3 +48,3 @@ },

},
"gitHead": "4fc9d282ff7ab2fa9040b775aeca7c30f5167b17"
"gitHead": "fe23a511edf816a3fea58d74856c2749a9de1463"
}

@@ -5,3 +5,3 @@ "use strict";

const pkg = require('expo-file-system/package.json');
const withFileSystem = config => {
const withFileSystem = (config) => {
return config_plugins_1.AndroidConfig.Permissions.withPermissions(config, [

@@ -8,0 +8,0 @@ 'android.permission.READ_EXTERNAL_STORAGE',

@@ -5,3 +5,3 @@ import { AndroidConfig, ConfigPlugin, createRunOncePlugin } from '@expo/config-plugins';

const withFileSystem: ConfigPlugin = config => {
const withFileSystem: ConfigPlugin = (config) => {
return AndroidConfig.Permissions.withPermissions(config, [

@@ -8,0 +8,0 @@ 'android.permission.READ_EXTERNAL_STORAGE',

@@ -1,2 +0,2 @@

import { NativeModulesProxy } from '@unimodules/core';
import { NativeModulesProxy } from 'expo-modules-core';

@@ -3,0 +3,0 @@ import ExponentFileSystemShim from './ExponentFileSystemShim';

@@ -1,2 +0,2 @@

import { EventEmitter, Subscription, UnavailabilityError } from '@unimodules/core';
import { EventEmitter, Subscription, UnavailabilityError } from 'expo-modules-core';
import { Platform } from 'react-native';

@@ -10,3 +10,5 @@ import { v4 as uuidv4 } from 'uuid';

DownloadProgressCallback,
FileSystemNetworkTaskProgressCallback,
DownloadProgressData,
UploadProgressData,
DownloadResult,

@@ -50,3 +52,3 @@ EncodingType,

FileSystemUploadType,
ProgressEvent,
FileSystemNetworkTaskProgressCallback,
ReadingOptions,

@@ -95,3 +97,3 @@ WritingOptions,

} else {
return new Promise(function(resolve, reject) {
return new Promise(function (resolve, reject) {
resolve(fileUri);

@@ -212,3 +214,3 @@ });

options?: DownloadOptions,
callback?: DownloadProgressCallback,
callback?: FileSystemNetworkTaskProgressCallback<DownloadProgressData>,
resumeData?: string

@@ -219,29 +221,144 @@ ): DownloadResumable {

export class DownloadResumable {
_uuid: string;
_url: string;
_fileUri: string;
_options: DownloadOptions;
_resumeData?: string;
_callback?: DownloadProgressCallback;
_subscription?: Subscription | null;
_emitter: EventEmitter;
export function createUploadTask(
url: string,
fileUri: string,
options?: FileSystemUploadOptions,
callback?: FileSystemNetworkTaskProgressCallback<UploadProgressData>
): UploadTask {
return new UploadTask(url, fileUri, options, callback);
}
export abstract class FileSystemCancellableNetworkTask<
T extends DownloadProgressData | UploadProgressData
> {
private _uuid = uuidv4();
protected taskWasCanceled = false;
private emitter = new EventEmitter(ExponentFileSystem);
private subscription?: Subscription | null;
public async cancelAsync(): Promise<void> {
if (!ExponentFileSystem.networkTaskCancelAsync) {
throw new UnavailabilityError('expo-file-system', 'networkTaskCancelAsync');
}
this.removeSubscription();
this.taskWasCanceled = true;
return await ExponentFileSystem.networkTaskCancelAsync(this.uuid);
}
protected isTaskCancelled(): boolean {
if (this.taskWasCanceled) {
console.warn('This task was already canceled.');
return true;
}
return false;
}
protected get uuid(): string {
return this._uuid;
}
protected abstract getEventName(): string;
protected abstract getCallback(): FileSystemNetworkTaskProgressCallback<T> | undefined;
protected addSubscription() {
if (this.subscription) {
return;
}
this.subscription = this.emitter.addListener(this.getEventName(), (event: ProgressEvent<T>) => {
if (event.uuid === this.uuid) {
const callback = this.getCallback();
if (callback) {
callback(event.data);
}
}
});
}
protected removeSubscription() {
if (!this.subscription) {
return;
}
this.emitter.removeSubscription(this.subscription);
this.subscription = null;
}
}
export class UploadTask extends FileSystemCancellableNetworkTask<UploadProgressData> {
private options: FileSystemUploadOptions;
constructor(
url: string,
fileUri: string,
options: DownloadOptions = {},
callback?: DownloadProgressCallback,
resumeData?: string
private url: string,
private fileUri: string,
options?: FileSystemUploadOptions,
private callback?: FileSystemNetworkTaskProgressCallback<UploadProgressData>
) {
this._uuid = uuidv4();
this._url = url;
this._fileUri = fileUri;
this._options = options;
this._resumeData = resumeData;
this._callback = callback;
this._subscription = null;
this._emitter = new EventEmitter(ExponentFileSystem);
super();
const httpMethod = (options?.httpMethod?.toUpperCase ||
'POST') as FileSystemAcceptedUploadHttpMethod;
this.options = {
sessionType: FileSystemSessionType.BACKGROUND,
uploadType: FileSystemUploadType.BINARY_CONTENT,
...options,
httpMethod,
};
}
protected getEventName(): string {
return 'expo-file-system.uploadProgress';
}
protected getCallback(): FileSystemNetworkTaskProgressCallback<UploadProgressData> | undefined {
return this.callback;
}
public async uploadAsync(): Promise<FileSystemUploadResult | undefined> {
if (!ExponentFileSystem.uploadTaskStartAsync) {
throw new UnavailabilityError('expo-file-system', 'uploadTaskStartAsync');
}
if (this.isTaskCancelled()) {
return;
}
this.addSubscription();
const result = await ExponentFileSystem.uploadTaskStartAsync(
this.url,
this.fileUri,
this.uuid,
this.options
);
this.removeSubscription();
return result;
}
}
export class DownloadResumable extends FileSystemCancellableNetworkTask<DownloadProgressData> {
constructor(
private url: string,
private _fileUri: string,
private options: DownloadOptions = {},
private callback?: FileSystemNetworkTaskProgressCallback<DownloadProgressData>,
private resumeData?: string
) {
super();
}
public get fileUri(): string {
return this._fileUri;
}
protected getEventName(): string {
return 'expo-file-system.downloadProgress';
}
protected getCallback(): FileSystemNetworkTaskProgressCallback<DownloadProgressData> | undefined {
return this.callback;
}
async downloadAsync(): Promise<FileSystemDownloadResult | undefined> {

@@ -251,9 +368,14 @@ if (!ExponentFileSystem.downloadResumableStartAsync) {

}
this._addSubscription();
if (this.isTaskCancelled()) {
return;
}
this.addSubscription();
return await ExponentFileSystem.downloadResumableStartAsync(
this._url,
this.url,
this._fileUri,
this._uuid,
this._options,
this._resumeData
this.uuid,
this.options,
this.resumeData
);

@@ -266,6 +388,15 @@ }

}
const pauseResult = await ExponentFileSystem.downloadResumablePauseAsync(this._uuid);
this._removeSubscription();
if (this.isTaskCancelled()) {
return {
fileUri: this._fileUri,
options: this.options,
url: this.url,
};
}
const pauseResult = await ExponentFileSystem.downloadResumablePauseAsync(this.uuid);
this.removeSubscription();
if (pauseResult) {
this._resumeData = pauseResult.resumeData;
this.resumeData = pauseResult.resumeData;
return this.savable();

@@ -281,9 +412,14 @@ } else {

}
this._addSubscription();
if (this.isTaskCancelled()) {
return;
}
this.addSubscription();
return await ExponentFileSystem.downloadResumableStartAsync(
this._url,
this._fileUri,
this._uuid,
this._options,
this._resumeData
this.url,
this.fileUri,
this.uuid,
this.options,
this.resumeData
);

@@ -294,33 +430,8 @@ }

return {
url: this._url,
fileUri: this._fileUri,
options: this._options,
resumeData: this._resumeData,
url: this.url,
fileUri: this.fileUri,
options: this.options,
resumeData: this.resumeData,
};
}
_addSubscription(): void {
if (this._subscription) {
return;
}
this._subscription = this._emitter.addListener(
'expo-file-system.downloadProgress',
(event: ProgressEvent) => {
if (event.uuid === this._uuid) {
const callback = this._callback;
if (callback) {
callback(event.data);
}
}
}
);
}
_removeSubscription(): void {
if (!this._subscription) {
return;
}
this._emitter.removeSubscription(this._subscription);
this._subscription = null;
}
}

@@ -327,0 +438,0 @@

@@ -66,4 +66,11 @@ export enum FileSystemSessionType {

export type DownloadProgressCallback = (data: DownloadProgressData) => void;
export type FileSystemNetworkTaskProgressCallback<
T extends DownloadProgressData | UploadProgressData
> = (data: T) => void;
/**
* @deprecated use `NetworkTaskProgressCallback<DownloadProgressData>` instead
*/
export type DownloadProgressCallback = FileSystemNetworkTaskProgressCallback<DownloadProgressData>;
export type DownloadProgressData = {

@@ -74,2 +81,7 @@ totalBytesWritten: number;

export type UploadProgressData = {
totalByteSent: number;
totalBytesExpectedToSend: number;
};
export type DownloadPauseState = {

@@ -117,8 +129,5 @@ url: string;

export type ProgressEvent = {
export type ProgressEvent<T> = {
uuid: string;
data: {
totalBytesWritten: number;
totalBytesExpectedToWrite: number;
};
data: T;
};

@@ -162,2 +171,4 @@

readonly createSAFFileAsync?: PlatformMethod;
readonly networkTaskCancelAsync?: PlatformMethod;
readonly uploadTaskStartAsync?: PlatformMethod;
startObserving?: () => void;

@@ -164,0 +175,0 @@ stopObserving?: () => void;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc