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

openapi-ts-json-schema

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

openapi-ts-json-schema - npm Package Compare versions

Comparing version 0.8.0 to 0.9.0

dist/utils/convertOpenApiPathsParameters.d.ts

4

dist/openapiToTsJsonSchema.js

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

});
const jsonSchema = (0, utils_1.convertOpenApiParameters)(dereferencedJsonSchema);
const jsonSchema = (0, utils_1.convertOpenApiPathsParameters)(dereferencedJsonSchema);
const schemaMetaDataMap = new Map();

@@ -115,3 +115,3 @@ /**

...returnPayload,
utils: { makeRelativePath: utils_1.makeRelativePath, formatTypeScript: utils_1.formatTypeScript, saveFile: utils_1.saveFile },
utils: { makeRelativeModulePath: utils_1.makeRelativeModulePath, formatTypeScript: utils_1.formatTypeScript, saveFile: utils_1.saveFile },
});

@@ -118,0 +118,0 @@ }

import type { Plugin } from '../types';
declare const fastifyIntegrationPlugin: Plugin<{
sharedSchemasFilter?: ({ schemaId }: {
schemaId: string;
sharedSchemasFilter?: ({ id }: {
id: string;
}) => boolean;
} | void>;
export default fastifyIntegrationPlugin;

@@ -8,10 +8,10 @@ "use strict";

.map(([id, schema]) => schema)
.map(({ schemaAbsoluteImportPath, schemaUniqueName, schemaId, isRef }) => {
.map(({ absoluteImportPath, uniqueName, id, isRef }) => {
return {
importPath: utils.makeRelativePath({
importPath: utils.makeRelativeModulePath({
fromDirectory: outputPath,
to: schemaAbsoluteImportPath,
to: absoluteImportPath,
}),
schemaUniqueName,
schemaId,
uniqueName,
id,
isRef,

@@ -23,3 +23,3 @@ };

const nonRefSchemas = allSchemas.filter((schema) => !schema.isRef);
const sharedSchemas = nonRefSchemas.filter(({ schemaId }) => sharedSchemasFilter({ schemaId }));
const sharedSchemas = nonRefSchemas.filter(({ id }) => sharedSchemasFilter({ id }));
let output = '// File autogenerated with "openapi-ts-json-schema". Do not edit :)';

@@ -29,3 +29,3 @@ // Generate JSON schemas import statements

[...refSchemas, ...sharedSchemas].forEach((schema) => {
output += `\n import ${schema.schemaUniqueName} from "${schema.importPath}";`;
output += `\n import ${schema.uniqueName} from "${schema.importPath}";`;
});

@@ -35,3 +35,3 @@ // Generate JSON schema objects with $id prop

[...refSchemas, ...sharedSchemas].forEach((schema) => {
output += `\n const ${schema.schemaUniqueName}WithId = {...${schema.schemaUniqueName}, $id: "${schema.schemaId}"} as const;`;
output += `\n const ${schema.uniqueName}WithId = {...${schema.uniqueName}, $id: "${schema.id}"} as const;`;
});

@@ -43,3 +43,3 @@ // RefSchemas type: generate TS tuple TS type containing the types of all $ref JSON schema

${refSchemas
.map((schema) => `typeof ${schema.schemaUniqueName}WithId`)
.map((schema) => `typeof ${schema.uniqueName}WithId`)
.join(',')}

@@ -51,5 +51,3 @@ ];`;

export const refSchemas = [
${refSchemas
.map((schema) => `${schema.schemaUniqueName}WithId`)
.join(',')}
${refSchemas.map((schema) => `${schema.uniqueName}WithId`).join(',')}
];`;

@@ -60,5 +58,3 @@ // sharedSchemas: generate an array of user-defined schemas to be registered with `fastify.addSchema`

export const sharedSchemas = [
${sharedSchemas
.map((schema) => `${schema.schemaUniqueName}WithId`)
.join(',')}
${sharedSchemas.map((schema) => `${schema.uniqueName}WithId`).join(',')}
];`;

@@ -65,0 +61,0 @@ // Format and save file

@@ -8,22 +8,22 @@ import type { JSONSchema4, JSONSchema6, JSONSchema7 } from 'json-schema';

}) => void;
import type { makeRelativePath, formatTypeScript, saveFile } from './utils';
import type { makeRelativeModulePath, formatTypeScript, saveFile } from './utils';
/**
* @prop `schemaFileName` - Valid filename for given schema (without extension). Eg: `"MySchema"`
* @prop `schemaAbsoluteDirName` - Absolute path pointing to schema folder. Eg: `"/output/path/components/schemas"`
* @prop `schemaAbsolutePath` - Absolute path pointing to schema file. Eg: `"/output/path/components/schemas/MySchema.ts"`
* @prop `schemaAbsoluteImportPath` - Absolute import path (without extension). Eg: `"/output/path/components/schemas/MySchema"`
* @prop `schemaUniqueName` - Unique JavaScript identifier used as import name. Eg: `"componentsSchemasMySchema"`
* @prop `schemaId` - JSON schema Compound Schema Document `$id`. Eg `"/components/schemas/MySchema"`
* @prop `originalSchema` - Original dereferenced JSON schema
* @prop `isRef` - True if schemas is used as `$ref`
* Meta data for representing a specific openApi definition
* @property `id` - JSON schema Compound Schema Document `$id`. Eg `"/components/schemas/MySchema"`
* @property `isRef` - True if schemas is used as `$ref`
* @property `uniqueName` - Unique JavaScript identifier used as import name. Eg: `"componentsSchemasMySchema"`
* @property `originalSchema` - Original dereferenced JSON schema
*
* @property `absoluteDirName` - Absolute path pointing to schema folder (posix or win32). Eg: `"Users/username/output/path/components/schemas"`
* @property `absolutePath` - Absolute path pointing to schema file (posix or win32). Eg: `"Users/username/output/path/components/schemas/MySchema.ts"`
* @property `absoluteImportPath` - Absolute import path (posix or win32, without extension). Eg: `"Users/username/output/path/components/schemas/MySchema"`
*/
export type SchemaMetaData = {
schemaFileName: string;
schemaAbsoluteDirName: string;
schemaAbsolutePath: string;
schemaAbsoluteImportPath: string;
schemaUniqueName: string;
schemaId: string;
id: string;
isRef: boolean;
uniqueName: string;
originalSchema: JSONSchema;
isRef: boolean;
absoluteDirName: string;
absolutePath: string;
absoluteImportPath: string;
};

@@ -40,3 +40,3 @@ export type SchemaMetaDataMap = Map<string, // Schema file relative path

utils: {
makeRelativePath: typeof makeRelativePath;
makeRelativeModulePath: typeof makeRelativeModulePath;
formatTypeScript: typeof formatTypeScript;

@@ -43,0 +43,0 @@ saveFile: typeof saveFile;

@@ -10,3 +10,2 @@ "use strict";

const namify_1 = __importDefault(require("namify"));
const filenamify_1 = __importDefault(require("filenamify"));
const _1 = require(".");

@@ -21,15 +20,15 @@ /*

if (!schemaMetaDataMap.has(ref)) {
const { schemaRelativeDirName, schemaName, schemaRelativePath } = (0, _1.refToPath)(ref);
const schemaAbsoluteDirName = node_path_1.default.join(outputPath, schemaRelativeDirName);
const schemaFileName = (0, filenamify_1.default)(schemaName, { replacement: '|' });
const schemaAbsoluteImportPath = node_path_1.default.join(schemaAbsoluteDirName, schemaFileName);
const refPath = (0, _1.parseRef)(ref);
const { schemaRelativeDirName, schemaName } = (0, _1.refToPath)(ref);
const absoluteDirName = node_path_1.default.join(outputPath, schemaRelativeDirName);
const schemaFileName = (0, _1.filenamify)(schemaName);
const absoluteImportPath = node_path_1.default.join(absoluteDirName, schemaFileName);
const metaInfo = {
id: `/${refPath}`,
uniqueName: (0, namify_1.default)(refPath),
isRef,
originalSchema: schema,
schemaId: `/${schemaRelativePath}`,
schemaFileName,
schemaAbsoluteDirName,
schemaAbsoluteImportPath,
schemaAbsolutePath: schemaAbsoluteImportPath + '.ts',
schemaUniqueName: (0, namify_1.default)(schemaRelativePath),
isRef,
absoluteDirName,
absoluteImportPath,
absolutePath: absoluteImportPath + '.ts',
};

@@ -36,0 +35,0 @@ schemaMetaDataMap.set(ref, metaInfo);

import type { OpenApiSchema } from '../types';
export declare function convertOpenApiToJsonSchema(schema: OpenApiSchema): import("json-schema").JSONSchema4;
/**
* Traverse the openAPI schema tree an brutally try to convert
* everything possible to JSON schema. We are probably overdoing since we process any object
* @TODO Find a cleaner way to convert to JSON schema all the existing OpenAPI schemas
* @NOTE We are currently skipping arrays
*/
export declare function convertOpenApiToJsonSchema(schema: OpenApiSchema): Record<string, unknown>;
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertOpenApiToJsonSchema = void 0;
const map_obj_1 = __importDefault(require("map-obj"));
const openapi_schema_to_json_schema_1 = require("@openapi-contrib/openapi-schema-to-json-schema");
function convertOpenApiToJsonSchema(schema) {
const _1 = require("./");
function convertToJsonSchema(value) {
if (!(0, _1.isObject)(value)) {
return value;
}
/**
* @openapi-contrib/openapi-schema-to-json-schema doesn't convert definitions by default,
* Here we convert all direct children of components
* https://swagger.io/specification/#components-object
* https://github.com/openapi-contrib/openapi-schema-to-json-schema#definitionkeywords-array
* type as array is not a valid OpenAPI value
* https://swagger.io/docs/specification/data-models/data-types#mixed-types
*/
const definitionKeywords = ['components'];
if ('components' in schema) {
definitionKeywords.push(...Object.keys(schema.components).map((field) => `components.${field}`));
if ('type' in value && Array.isArray(value.type)) {
return value;
}
const jsonSchema = (0, openapi_schema_to_json_schema_1.fromSchema)(schema, {
definitionKeywords,
});
return jsonSchema;
const schema = (0, openapi_schema_to_json_schema_1.fromSchema)(value);
// $schema is appended by @openapi-contrib/openapi-schema-to-json-schema
delete schema.$schema;
return schema;
}
/**
* Traverse the openAPI schema tree an brutally try to convert
* everything possible to JSON schema. We are probably overdoing since we process any object
* @TODO Find a cleaner way to convert to JSON schema all the existing OpenAPI schemas
* @NOTE We are currently skipping arrays
*/
function convertOpenApiToJsonSchema(schema) {
return (0, map_obj_1.default)(schema, (key, value) => {
return [key, convertToJsonSchema(value)];
}, { deep: true });
}
exports.convertOpenApiToJsonSchema = convertOpenApiToJsonSchema;
export { patchJsonSchema } from './makeTsJsonSchema/patchJsonSchema';
export { makeTsJsonSchema } from './makeTsJsonSchema';
export { convertOpenApiParameters } from './convertOpenApiParameters';
export { convertOpenApiPathsParameters } from './convertOpenApiPathsParameters';
export { convertOpenApiToJsonSchema } from './convertOpenApiToJsonSchema';
export { makeTsJsonSchemaFiles } from './makeTsJsonSchemaFiles';
export { parseRef } from './parseRef';
export { refToPath } from './refToPath';

@@ -12,5 +13,7 @@ export { pathToRef } from './pathToRef';

export { addSchemaToMetaData } from './addSchemaToMetaData';
export { isObject } from './isObject';
export { filenamify } from './filenamify';
export { clearFolder } from './clearFolder';
export { makeRelativePath } from './makeRelativePath';
export { makeRelativeModulePath } from './makeRelativeModulePath';
export { formatTypeScript } from './formatTypeScript';
export { saveFile } from './saveFile';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.saveFile = exports.formatTypeScript = exports.makeRelativePath = exports.clearFolder = exports.addSchemaToMetaData = exports.replacePlaceholdersWithImportedSchemas = exports.replaceInlinedRefsWithStringPlaceholder = exports.refToPlaceholder = exports.PLACEHOLDER_REGEX = exports.REF_SYMBOL = exports.pathToRef = exports.refToPath = exports.makeTsJsonSchemaFiles = exports.convertOpenApiToJsonSchema = exports.convertOpenApiParameters = exports.makeTsJsonSchema = exports.patchJsonSchema = void 0;
exports.saveFile = exports.formatTypeScript = exports.makeRelativeModulePath = exports.clearFolder = exports.filenamify = exports.isObject = exports.addSchemaToMetaData = exports.replacePlaceholdersWithImportedSchemas = exports.replaceInlinedRefsWithStringPlaceholder = exports.refToPlaceholder = exports.PLACEHOLDER_REGEX = exports.REF_SYMBOL = exports.pathToRef = exports.refToPath = exports.parseRef = exports.makeTsJsonSchemaFiles = exports.convertOpenApiToJsonSchema = exports.convertOpenApiPathsParameters = exports.makeTsJsonSchema = exports.patchJsonSchema = void 0;
var patchJsonSchema_1 = require("./makeTsJsonSchema/patchJsonSchema");

@@ -8,4 +8,4 @@ Object.defineProperty(exports, "patchJsonSchema", { enumerable: true, get: function () { return patchJsonSchema_1.patchJsonSchema; } });

Object.defineProperty(exports, "makeTsJsonSchema", { enumerable: true, get: function () { return makeTsJsonSchema_1.makeTsJsonSchema; } });
var convertOpenApiParameters_1 = require("./convertOpenApiParameters");
Object.defineProperty(exports, "convertOpenApiParameters", { enumerable: true, get: function () { return convertOpenApiParameters_1.convertOpenApiParameters; } });
var convertOpenApiPathsParameters_1 = require("./convertOpenApiPathsParameters");
Object.defineProperty(exports, "convertOpenApiPathsParameters", { enumerable: true, get: function () { return convertOpenApiPathsParameters_1.convertOpenApiPathsParameters; } });
var convertOpenApiToJsonSchema_1 = require("./convertOpenApiToJsonSchema");

@@ -15,2 +15,4 @@ Object.defineProperty(exports, "convertOpenApiToJsonSchema", { enumerable: true, get: function () { return convertOpenApiToJsonSchema_1.convertOpenApiToJsonSchema; } });

Object.defineProperty(exports, "makeTsJsonSchemaFiles", { enumerable: true, get: function () { return makeTsJsonSchemaFiles_1.makeTsJsonSchemaFiles; } });
var parseRef_1 = require("./parseRef");
Object.defineProperty(exports, "parseRef", { enumerable: true, get: function () { return parseRef_1.parseRef; } });
var refToPath_1 = require("./refToPath");

@@ -30,6 +32,10 @@ Object.defineProperty(exports, "refToPath", { enumerable: true, get: function () { return refToPath_1.refToPath; } });

Object.defineProperty(exports, "addSchemaToMetaData", { enumerable: true, get: function () { return addSchemaToMetaData_1.addSchemaToMetaData; } });
var isObject_1 = require("./isObject");
Object.defineProperty(exports, "isObject", { enumerable: true, get: function () { return isObject_1.isObject; } });
var filenamify_1 = require("./filenamify");
Object.defineProperty(exports, "filenamify", { enumerable: true, get: function () { return filenamify_1.filenamify; } });
var clearFolder_1 = require("./clearFolder");
Object.defineProperty(exports, "clearFolder", { enumerable: true, get: function () { return clearFolder_1.clearFolder; } });
var makeRelativePath_1 = require("./makeRelativePath");
Object.defineProperty(exports, "makeRelativePath", { enumerable: true, get: function () { return makeRelativePath_1.makeRelativePath; } });
var makeRelativeModulePath_1 = require("./makeRelativeModulePath");
Object.defineProperty(exports, "makeRelativeModulePath", { enumerable: true, get: function () { return makeRelativeModulePath_1.makeRelativeModulePath; } });
var formatTypeScript_1 = require("./formatTypeScript");

@@ -36,0 +42,0 @@ Object.defineProperty(exports, "formatTypeScript", { enumerable: true, get: function () { return formatTypeScript_1.formatTypeScript; } });

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

const __1 = require("..");
function isObject(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
const __2 = require("../");
/**

@@ -13,3 +11,3 @@ * Retrieve REF_SYMBOL prop value

function getRef(node) {
if (isObject(node) &&
if ((0, __2.isObject)(node) &&
__1.REF_SYMBOL in node &&

@@ -16,0 +14,0 @@ typeof node[__1.REF_SYMBOL] === 'string') {

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

async function makeTsJsonSchema({ metaData, schemaMetaDataMap, refHandling, schemaPatcher, }) {
const { originalSchema, schemaAbsoluteDirName } = metaData;
const { originalSchema, absoluteDirName } = metaData;
// "inline" refHandling doesn't need replacing inlined refs

@@ -38,3 +38,3 @@ const schemaWithPlaceholders = refHandling === 'import' || refHandling === 'keep'

schemaAsText: tsSchema,
schemaAbsoluteDirName,
absoluteDirName,
schemaMetaDataMap,

@@ -41,0 +41,0 @@ });

@@ -5,6 +5,6 @@ import type { SchemaMetaDataMap } from '../../types';

*/
export declare function replacePlaceholdersWithImportedSchemas({ schemaAsText, schemaAbsoluteDirName, schemaMetaDataMap, }: {
export declare function replacePlaceholdersWithImportedSchemas({ schemaAsText, absoluteDirName, schemaMetaDataMap, }: {
schemaAsText: string;
schemaAbsoluteDirName: string;
absoluteDirName: string;
schemaMetaDataMap: SchemaMetaDataMap;
}): string;

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

*/
function replacePlaceholdersWithImportedSchemas({ schemaAsText, schemaAbsoluteDirName, schemaMetaDataMap, }) {
function replacePlaceholdersWithImportedSchemas({ schemaAsText, absoluteDirName, schemaMetaDataMap, }) {
const importStatements = new Set();

@@ -20,9 +20,9 @@ // Replace placeholder occurrences with the relevant imported schema name

// Evaluate imported schema relative path from current schema file
const importedSchemaRelativePath = (0, __1.makeRelativePath)({
fromDirectory: schemaAbsoluteDirName,
to: importedSchema.schemaAbsoluteImportPath,
const importedSchemaRelativePath = (0, __1.makeRelativeModulePath)({
fromDirectory: absoluteDirName,
to: importedSchema.absoluteImportPath,
});
const { schemaUniqueName } = importedSchema;
importStatements.add(`import ${schemaUniqueName} from "${importedSchemaRelativePath}"`);
return schemaUniqueName;
const { uniqueName } = importedSchema;
importStatements.add(`import ${uniqueName} from "${importedSchemaRelativePath}"`);
return uniqueName;
});

@@ -29,0 +29,0 @@ if (importStatements.size > 0) {

@@ -16,6 +16,6 @@ "use strict";

});
const { schemaAbsolutePath } = metaData;
await (0, _1.saveFile)({ path: [schemaAbsolutePath], data: tsSchema });
const { absolutePath } = metaData;
await (0, _1.saveFile)({ path: [absolutePath], data: tsSchema });
}
}
exports.makeTsJsonSchemaFiles = makeTsJsonSchemaFiles;

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

/**
* Generate a local OpenAPI ref from a relative path and a schema name
*/
export declare function pathToRef({ schemaRelativeDirName, schemaName, }: {

@@ -5,0 +2,0 @@ schemaRelativeDirName: string;

@@ -8,10 +8,18 @@ "use strict";

const node_path_1 = __importDefault(require("node:path"));
const filenamify_1 = __importDefault(require("filenamify"));
const _1 = require("./");
/**
* Generate a local OpenAPI ref from a relative path and a schema name
*/
const TRALING_SLASH_REGEX = /\/$/;
function pathToRef({ schemaRelativeDirName, schemaName, }) {
return ('#/' +
node_path_1.default.join(schemaRelativeDirName.replaceAll('.', '/'), (0, filenamify_1.default)(schemaName, { replacement: '|' })));
node_path_1.default
.normalize(schemaRelativeDirName)
// Supporting definitionPathsToGenerateFrom dot notation
.replaceAll('.', '/')
.replaceAll('\\', '/')
.replace(TRALING_SLASH_REGEX, '') +
'/' +
(0, _1.filenamify)(schemaName));
}
exports.pathToRef = pathToRef;

@@ -8,5 +8,4 @@ /**

export declare function refToPath(ref: string): {
schemaRelativePath: string;
schemaRelativeDirName: string;
schemaName: string;
};

@@ -8,2 +8,3 @@ "use strict";

const node_path_1 = __importDefault(require("node:path"));
const _1 = require(".");
/**

@@ -16,16 +17,8 @@ * Parses OpenAPI local refs (#/components/schema/Foo) to the derive the expected schema output path

function refToPath(ref) {
/* c8 ignore start */
if (!ref.startsWith('#/')) {
throw new Error(`[openapi-ts-json-schema] Unsupported ref value: "${ref}"`);
}
/* c8 ignore stop */
const refPath = ref.replace('#/', '');
const schemaName = node_path_1.default.basename(refPath);
const schemaRelativeDirName = node_path_1.default.dirname(refPath);
const refPath = (0, _1.parseRef)(ref);
return {
schemaRelativePath: node_path_1.default.join(schemaRelativeDirName, schemaName),
schemaRelativeDirName,
schemaName,
schemaRelativeDirName: node_path_1.default.dirname(refPath),
schemaName: node_path_1.default.basename(refPath),
};
}
exports.refToPath = refToPath;
{
"name": "openapi-ts-json-schema",
"version": "0.8.0",
"version": "0.9.0",
"description": "OpenAPI to JSON schema generator with TypeScript in mind",

@@ -51,3 +51,3 @@ "main": "./dist/index.js",

"engines": {
"node": "^18.0.0"
"node": ">=18.0.0"
},

@@ -54,0 +54,0 @@ "simple-git-hooks": {

@@ -116,13 +116,5 @@ # openapi-ts-json-schema

{
schemaId: string;
id: string;
// JSON schema Compound Schema Document `$id`. Eg: `"/components/schemas/MySchema"`
schemaFileName: string;
// Valid filename for given schema (without extension). Eg: `"MySchema"`
schemaAbsoluteDirName: string;
// Absolute path pointing to schema folder. Eg: `"/output/path/components/schemas"`
schemaAbsolutePath: string;
// Absolute path pointing to schema file. Eg: `"/output/path/components/schemas/MySchema.ts"`
schemaAbsoluteImportPath: string;
// Absolute import path (without extension). Eg: `"/output/path/components/schemas/MySchema"`
schemaUniqueName: string;
uniqueName: string;
// Unique JavaScript identifier used as import name. Eg: `"componentsSchemasMySchema"`

@@ -133,2 +125,9 @@ originalSchema: JSONSchema | string;

// True if schemas is used as a `$ref`
absoluteDirName: string;
// Absolute path pointing to schema folder (posix or win32). Eg: `"Users/username/output/path/components/schemas"`
absolutePath: string;
// Absolute path pointing to schema file (posix or win32). Eg: `"Users/username/output/path/components/schemas/MySchema.ts"`
absoluteImportPath: string;
// Absolute import path (posix or win32, without extension). Eg: `"Users/username/output/path/components/schemas/MySchema"`
}

@@ -150,7 +149,6 @@ >;

- Consider merging "operation" and "path" parameters definition
- Consider removing required `definitionPathsToGenerateFrom` option in favour of exporting the whole OpenAPI definitions based on the structure defined in specs
- Improve external `#ref`s handling (currently being inlined and duplicated)
- Find a way to merge multiple different OpenApi definitions consistently
- Consider adding a way to customize the values of the generated JSON schema ids. This could be beneficial even in case of multiple schemas being merged with plugins
- Find a way to merge multiple different OpenApi definitions consistently
- Improve external `#ref`s handling
- Consider implementing an option to inline circular $refs with a configurable nesting level

@@ -157,0 +155,0 @@

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