New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

solidity-docgen

Package Overview
Dependencies
Maintainers
2
Versions
90
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

solidity-docgen - npm Package Compare versions

Comparing version 0.6.0-beta.3 to 0.6.0-beta.4

dist/templates.d.ts

30

dist/config.d.ts

@@ -6,19 +6,25 @@ import { SourceUnit } from 'solidity-ast';

* The directory where rendered pages will be written.
* Defaults to 'docs'.
*/
output?: string;
outputDir?: string;
/**
* A function that returns the page assigned to a documentable item
* (contract, function, etc.) given the AST node for the item and the source
* unit where it is defined.
* Defaults to assigning all items to an index.md file.
* A directory of custom templates that should take precedence over the
* theme's templates.
*/
pages?: (item: DocItem, file: SourceUnit) => string | undefined;
templates?: string;
/**
* An array of directories or built-in names that should be searched
* sequentially for templates and helpers. A single string is equal to an
* array with only that string.
* Defaults to built-in markdown templates.
* The name of the built-in templates that will be used by default.
* Defaults to 'markdown'.
*/
templates?: string[] | string;
theme?: string;
/**
* The way documentable items (contracts, functions, etc.) will be organized
* in pages. Built in options are: 'single' for all items in one page, and
* 'items' for one page per item. More customization is possible by defining
* a function that returns a page path given the AST node for the item and
* the source unit where it is defined.
* Defaults to 'single'.
*/
pages?: 'single' | 'items' | ((item: DocItem, file: SourceUnit) => string | undefined);
/**
* Clean up the output by collapsing 3 or more contiguous newlines into only 2.

@@ -36,3 +42,3 @@ * Enabled by default.

}
export declare const defaults: Required<Config>;
export declare const defaults: Omit<Required<Config>, 'templates'>;
//# sourceMappingURL=config.d.ts.map

6

dist/config.js

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

root: process.cwd(),
output: 'docs',
pages: () => 'index.md',
templates: 'markdown',
outputDir: 'docs',
pages: 'single',
theme: 'markdown',
collapseNewlines: true,
};
//# sourceMappingURL=config.js.map

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

import { Templates } from './render';
import { Build } from './site';

@@ -10,7 +9,2 @@ import { Config } from './config';

export declare function main(builds: Build[], userConfig?: Config): Promise<void>;
/**
* The array of strings containing either directory paths or built-in names is
* searched sequentially for templates and helpers, and merged into an object.
*/
export declare function readTemplates(templates: string[], root: string): Promise<Templates>;
//# sourceMappingURL=main.d.ts.map
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -25,3 +6,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

Object.defineProperty(exports, "__esModule", { value: true });
exports.readTemplates = exports.main = void 0;
exports.main = void 0;
const path_1 = __importDefault(require("path"));

@@ -31,5 +12,4 @@ const fs_1 = require("fs");

const site_1 = require("./site");
const fs_exists_1 = require("./utils/fs-exists");
const ensure_array_1 = require("./utils/ensure-array");
const config_1 = require("./config");
const templates_1 = require("./templates");
/**

@@ -43,6 +23,6 @@ * Given a set of builds (i.e. solc outputs) and a user configuration, this

const site = (0, site_1.buildSite)(builds, config.pages);
const templates = await readTemplates((0, ensure_array_1.ensureArray)(config.templates), config.root);
const templates = await (0, templates_1.loadTemplates)(config.theme, config.root, config.templates);
const renderedSite = (0, render_1.render)(site, templates, config.collapseNewlines);
for (const { id, contents } of renderedSite) {
const outputFile = path_1.default.resolve(config.root, config.output, id);
const outputFile = path_1.default.resolve(config.root, config.outputDir, id);
await fs_1.promises.mkdir(path_1.default.dirname(outputFile), { recursive: true });

@@ -53,42 +33,2 @@ await fs_1.promises.writeFile(outputFile, contents);

exports.main = main;
/**
* The array of strings containing either directory paths or built-in names is
* searched sequentially for templates and helpers, and merged into an object.
*/
async function readTemplates(templates, root) {
const partials = {};
const helpers = {};
for (const nameOrPath of templates) {
// Look in src because built-in templates are not copied to dist
const templatesDir = await (0, fs_exists_1.findIn)(nameOrPath, [root, path_1.default.join(__dirname, '../src/templates')]);
if (templatesDir === undefined) {
throw new Error(`Templates directory '${nameOrPath}' not found`);
}
for (const t of await fs_1.promises.readdir(templatesDir)) {
const { name, ext } = path_1.default.parse(t);
if (!(name in partials) && ext === '.hbs') {
partials[name] = await fs_1.promises.readFile(path_1.default.join(templatesDir, t), 'utf8');
}
}
const helpersDir = await (0, fs_exists_1.findIn)(nameOrPath, [root, path_1.default.join(__dirname, './templates')]);
if (helpersDir === undefined) {
throw new Error(`Templates directory '${nameOrPath}' not found`);
}
const h = await Promise.resolve().then(() => __importStar(require(path_1.default.join(helpersDir, 'helpers')))).catch(() => undefined);
for (const name in h) {
if (!(name in helpers) && typeof h[name] === 'function') {
helpers[name] = h[name];
}
}
}
if (partials.page === undefined) {
throw new Error(`Missing 'page' template`);
}
return {
page: partials.page,
partials,
helpers,
};
}
exports.readTemplates = readTemplates;
//# sourceMappingURL=main.js.map
import { Site, DocItemWithContext } from './site';
export interface Templates {
page: string;
partials?: Record<string, string>;
helpers?: Record<string, (...args: unknown[]) => string>;
}
import { Templates } from './templates';
export interface RenderedPage {

@@ -8,0 +4,0 @@ id: string;

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

function render(site, templates, collapseNewlines) {
const template = buildTemplate(templates);
const rendered = [];
const renderPage = buildRenderer(templates);
const renderedPages = [];
for (const page of site.pages) {
let contents = template(page, { data: { site } });
let contents = renderPage(page, { data: { site } });
if (collapseNewlines) {
contents = contents.replace(/\n{3,}/g, '\n\n');
}
rendered.push({
renderedPages.push({
id: page.id,

@@ -23,3 +23,3 @@ contents,

}
return rendered;
return renderedPages;
}

@@ -40,14 +40,22 @@ exports.render = render;

}
function buildTemplate(templates) {
var _a, _b;
function buildRenderer(templates) {
var _a, _b, _c;
const pageTemplate = (_a = templates.partials) === null || _a === void 0 ? void 0 : _a.page;
if (pageTemplate === undefined) {
throw new Error(`Missing 'page' template`);
}
const H = handlebars_1.default.create();
for (const [name, body] of Object.entries((_a = templates.partials) !== null && _a !== void 0 ? _a : {})) {
H.registerPartial(name, H.compile(body));
for (const [name, getBody] of Object.entries((_b = templates.partials) !== null && _b !== void 0 ? _b : {})) {
let partial;
H.registerPartial(name, (...args) => {
partial !== null && partial !== void 0 ? partial : (partial = H.compile(getBody()));
return partial(...args);
});
}
for (const [name, fn] of Object.entries((_b = templates.helpers) !== null && _b !== void 0 ? _b : {})) {
for (const [name, fn] of Object.entries((_c = templates.helpers) !== null && _c !== void 0 ? _c : {})) {
H.registerHelper(name, fn);
}
H.registerPartial('item', itemPartial);
return H.compile(templates.page);
return H.compile('{{>page}}');
}
//# sourceMappingURL=render.js.map

@@ -23,12 +23,16 @@ "use strict";

}
testRender('static page', 'S08_AB', { page: 'a page' }, 'a page');
testRender('items', 'S08_AB', { page: '{{#each items}}{{name}}, {{/each}}' }, 'A, B, ');
testRender('static page', 'S08_AB', { partials: { page: () => 'a page' } }, 'a page');
testRender('items', 'S08_AB', { partials: { page: () => '{{#each items}}{{name}}, {{/each}}' } }, 'A, B, ');
testRender('partials', 'S08_AB', {
page: '{{#each items}}{{>part}}, {{/each}}',
partials: { part: '{{name}}' },
partials: {
page: () => '{{#each items}}{{>part}}, {{/each}}',
part: () => '{{name}}',
},
}, 'A, B, ');
testRender('item partial', 'S08_AB', {
page: '{{#each items}}{{>item}}, {{/each}}',
partials: { contract: '{{name}}' },
partials: {
page: () => '{{#each items}}{{>item}}, {{/each}}',
contract: () => '{{name}}',
},
}, 'A, B, ');
//# sourceMappingURL=render.test.js.map

@@ -9,3 +9,4 @@ import { ContractDefinition, SourceUnit } from 'solidity-ast';

}
export declare type PageAssigner = NonNullable<Config['pages']>;
export declare type PageStructure = NonNullable<Config['pages']>;
export declare type PageAssigner = Exclude<PageStructure, string>;
export interface Site {

@@ -32,3 +33,3 @@ items: DocItemWithContext[];

}
export declare function buildSite(builds: Build[], assign: PageAssigner): Site;
export declare function buildSite(builds: Build[], pageStructure: PageStructure): Site;
//# sourceMappingURL=site.d.ts.map

@@ -7,4 +7,9 @@ "use strict";

const clone_1 = require("./utils/clone");
function buildSite(builds, assign) {
const pageAssigner = {
single: () => 'index.md',
items: (item) => item.name,
};
function buildSite(builds, pageStructure) {
var _a;
const assign = typeof pageStructure === 'string' ? pageAssigner[pageStructure] : pageStructure;
const seen = new Set();

@@ -11,0 +16,0 @@ const items = [];

@@ -6,13 +6,15 @@ "use strict";

const accessors_1 = require("../accessors");
const arrays_equal_1 = require("./arrays-equal");
const execall_1 = require("./execall");
const scope_1 = require("./scope");
function parseNatspec(item) {
var _a, _b, _c, _d, _e;
var _f;
var _a, _b, _c, _d, _e, _f, _g;
var _h;
if (!item.__item_context)
throw new Error(`Not an item or item is missing context`);
if (!('documentation' in item && item.documentation))
return {};
let res = {};
const tagMatches = (0, execall_1.execAll)(/^(?:@(\w+|custom:[a-z][a-z-]*) )?((?:(?!^@(?:\w+|custom:[a-z][a-z-]*) )[^])*)/m, cleanUpDocstring(item.documentation.text));
const docString = 'documentation' in item && ((_a = item.documentation) === null || _a === void 0 ? void 0 : _a.text)
? cleanUpDocstring(item.documentation.text)
: '';
const tagMatches = (0, execall_1.execAll)(/^(?:@(\w+|custom:[a-z][a-z-]*) )?((?:(?!^@(?:\w+|custom:[a-z][a-z-]*) )[^])*)/m, docString);
let inheritFrom;

@@ -23,3 +25,3 @@ for (const [, tag = 'notice', content] of tagMatches) {

if (tag === 'dev' || tag === 'notice') {
(_a = res[tag]) !== null && _a !== void 0 ? _a : (res[tag] = '');
(_b = res[tag]) !== null && _b !== void 0 ? _b : (res[tag] = '');
res[tag] += content;

@@ -34,3 +36,3 @@ }

const [, name, description] = paramMatches;
(_b = res.params) !== null && _b !== void 0 ? _b : (res.params = []);
(_c = res.params) !== null && _c !== void 0 ? _c : (res.params = []);
res.params.push({ name, description: description.trim() });

@@ -43,3 +45,3 @@ }

}
(_c = res.returns) !== null && _c !== void 0 ? _c : (res.returns = []);
(_d = res.returns) !== null && _d !== void 0 ? _d : (res.returns = []);
const i = res.returns.length;

@@ -64,4 +66,4 @@ const p = item.returnParameters.parameters[i];

const key = tag.replace(/^custom:/, '');
(_d = res.custom) !== null && _d !== void 0 ? _d : (res.custom = {});
(_e = (_f = res.custom)[key]) !== null && _e !== void 0 ? _e : (_f[key] = '');
(_e = res.custom) !== null && _e !== void 0 ? _e : (res.custom = {});
(_f = (_h = res.custom)[key]) !== null && _f !== void 0 ? _f : (_h[key] = '');
res.custom[key] += content;

@@ -78,5 +80,14 @@ }

}
inheritFrom = [...(0, utils_1.findAll)('FunctionDefinition', parentContract)].find(f => f.name === item.name);
inheritFrom = [...(0, utils_1.findAll)('FunctionDefinition', parentContract)].find(f => { var _a; return (_a = item.baseFunctions) === null || _a === void 0 ? void 0 : _a.includes(f.id); });
}
}
if (docString.length === 0) {
if ('baseFunctions' in item && ((_g = item.baseFunctions) === null || _g === void 0 ? void 0 : _g.length) === 1) {
const baseFn = item.__item_context.build.deref('FunctionDefinition', item.baseFunctions[0]);
const shouldInherit = item.nodeType === 'VariableDeclaration' || (0, arrays_equal_1.arraysEqual)(item.parameters.parameters, baseFn.parameters.parameters, p => p.name);
if (shouldInherit) {
inheritFrom = baseFn;
}
}
}
if (res.dev)

@@ -89,3 +100,2 @@ res.dev = res.dev.trim();

}
// [TODO] inheritance by default as specified by solidity
return res;

@@ -92,0 +102,0 @@ }

{
"name": "solidity-docgen",
"version": "0.6.0-beta.3",
"version": "0.6.0-beta.4",
"description": "Documentation generator for Solidity smart contracts.",

@@ -5,0 +5,0 @@ "repository": "github:OpenZeppelin/solidity-docgen",

import { SourceUnit } from 'solidity-ast';
import { DocItem } from './doc-item';
import { PageAssigner } from './site';
import { PageStructure } from './site';

@@ -8,22 +8,29 @@ export interface UserConfig {

* The directory where rendered pages will be written.
* Defaults to 'docs'.
*/
output?: string;
outputDir?: string;
/**
* A function that returns the page assigned to a documentable item
* (contract, function, etc.) given the AST node for the item and the source
* unit where it is defined.
* Defaults to assigning all items to an index.md file.
* A directory of custom templates that should take precedence over the
* theme's templates.
*/
pages?: (item: DocItem, file: SourceUnit) => string | undefined;
templates?: string;
/**
* An array of directories or built-in names that should be searched
* sequentially for templates and helpers. A single string is equal to an
* array with only that string.
* Defaults to built-in markdown templates.
* The name of the built-in templates that will be used by default.
* Defaults to 'markdown'.
*/
templates?: string[] | string;
theme?: string;
/**
* The way documentable items (contracts, functions, etc.) will be organized
* in pages. Built in options are: 'single' for all items in one page, and
* 'items' for one page per item. More customization is possible by defining
* a function that returns a page path given the AST node for the item and
* the source unit where it is defined.
* Defaults to 'single'.
*/
pages?: 'single' | 'items' | ((item: DocItem, file: SourceUnit) => string | undefined);
/**
* Clean up the output by collapsing 3 or more contiguous newlines into only 2.

@@ -47,8 +54,8 @@ * Enabled by default.

export const defaults: Required<Config> = {
export const defaults: Omit<Required<Config>, 'templates'> = {
root: process.cwd(),
output: 'docs',
pages: () => 'index.md',
templates: 'markdown',
outputDir: 'docs',
pages: 'single',
theme: 'markdown',
collapseNewlines: true,
};
import path from 'path';
import { promises as fs } from 'fs';
import { SolcOutput } from 'solidity-ast/solc';
import { render, Templates } from './render';
import { Build, PageAssigner, buildSite } from './site';
import { exists, findIn } from './utils/fs-exists';
import { render } from './render';
import { Build, buildSite } from './site';
import { ensureArray } from './utils/ensure-array';
import { Config, defaults } from './config';
import { loadTemplates } from './templates';

@@ -20,7 +19,7 @@ /**

const templates = await readTemplates(ensureArray(config.templates), config.root);
const templates = await loadTemplates(config.theme, config.root, config.templates);
const renderedSite = render(site, templates, config.collapseNewlines);
for (const { id, contents } of renderedSite) {
const outputFile = path.resolve(config.root, config.output, id);
const outputFile = path.resolve(config.root, config.outputDir, id);
await fs.mkdir(path.dirname(outputFile), { recursive: true });

@@ -30,47 +29,1 @@ await fs.writeFile(outputFile, contents);

}
/**
* The array of strings containing either directory paths or built-in names is
* searched sequentially for templates and helpers, and merged into an object.
*/
export async function readTemplates(templates: string[], root: string): Promise<Templates> {
const partials: Record<string, string> = {};
const helpers: Record<string, any> = {};
for (const nameOrPath of templates) {
// Look in src because built-in templates are not copied to dist
const templatesDir = await findIn(nameOrPath, [root, path.join(__dirname, '../src/templates')]);
if (templatesDir === undefined) {
throw new Error(`Templates directory '${nameOrPath}' not found`);
}
for (const t of await fs.readdir(templatesDir)) {
const { name, ext } = path.parse(t);
if (!(name in partials) && ext === '.hbs') {
partials[name] = await fs.readFile(path.join(templatesDir, t), 'utf8');
}
}
const helpersDir = await findIn(nameOrPath, [root, path.join(__dirname, './templates')]);
if (helpersDir === undefined) {
throw new Error(`Templates directory '${nameOrPath}' not found`);
}
const h = await import(path.join(helpersDir, 'helpers')).catch(() => undefined);
for (const name in h) {
if (!(name in helpers) && typeof h[name] === 'function') {
helpers[name] = h[name];
}
}
}
if (partials.page === undefined) {
throw new Error(`Missing 'page' template`);
}
return {
page: partials.page,
partials,
helpers,
};
}
import test from './utils/test';
import path from 'path';
import { buildSite, PageAssigner } from './site';
import { itemPartialName, render, Templates } from './render';
import { buildSite, PageStructure } from './site';
import { itemPartialName, render } from './render';
import { NodeType } from 'solidity-ast/node';
import { Templates } from './templates';

@@ -16,3 +17,3 @@ interface TestSpec extends Templates {

const id = 'index.md';
const assign: PageAssigner = (_, f) => path.parse(f.absolutePath).name === file ? id : undefined;
const assign: PageStructure = (_, f) => path.parse(f.absolutePath).name === file ? id : undefined;

@@ -29,3 +30,3 @@ test(title, t => {

'S08_AB',
{ page: 'a page' },
{ partials: { page: () => 'a page' } },
'a page',

@@ -36,3 +37,3 @@ );

'S08_AB',
{ page: '{{#each items}}{{name}}, {{/each}}' },
{ partials: { page: () => '{{#each items}}{{name}}, {{/each}}' } },
'A, B, ',

@@ -44,4 +45,6 @@ );

{
page: '{{#each items}}{{>part}}, {{/each}}',
partials: { part: '{{name}}' },
partials: {
page: () => '{{#each items}}{{>part}}, {{/each}}',
part: () => '{{name}}',
},
},

@@ -54,6 +57,8 @@ 'A, B, ',

{
page: '{{#each items}}{{>item}}, {{/each}}',
partials: { contract: '{{name}}' },
partials: {
page: () => '{{#each items}}{{>item}}, {{/each}}',
contract: () => '{{name}}',
},
},
'A, B, ',
);

@@ -5,9 +5,4 @@ import Handlebars, { RuntimeOptions } from 'handlebars';

import { accessors, wrapWithAccessors } from './accessors';
import { Templates } from './templates';
export interface Templates {
page: string;
partials?: Record<string, string>;
helpers?: Record<string, (...args: unknown[]) => string>;
}
export interface RenderedPage {

@@ -25,10 +20,10 @@ id: string;

export function render(site: Site, templates: Templates, collapseNewlines?: boolean): RenderedPage[] {
const template = buildTemplate(templates);
const rendered: RenderedPage[] = [];
const renderPage = buildRenderer(templates);
const renderedPages: RenderedPage[] = [];
for (const page of site.pages) {
let contents = template(page, { data: { site } });
let contents = renderPage(page, { data: { site } });
if (collapseNewlines) {
contents = contents.replace(/\n{3,}/g, '\n\n');
}
rendered.push({
renderedPages.push({
id: page.id,

@@ -38,3 +33,3 @@ contents,

}
return rendered;
return renderedPages;
}

@@ -55,7 +50,16 @@

function buildTemplate(templates: Templates): (page: Page, options: TemplateOptions) => string {
function buildRenderer(templates: Templates): (page: Page, options: TemplateOptions) => string {
const pageTemplate = templates.partials?.page;
if (pageTemplate === undefined) {
throw new Error(`Missing 'page' template`);
}
const H = Handlebars.create();
for (const [name, body] of Object.entries(templates.partials ?? {})) {
H.registerPartial(name, H.compile(body));
for (const [name, getBody] of Object.entries(templates.partials ?? {})) {
let partial: HandlebarsTemplateDelegate | undefined;
H.registerPartial(name, (...args) => {
partial ??= H.compile(getBody());
return partial(...args);
});
}

@@ -69,3 +73,3 @@

return H.compile(templates.page);
return H.compile('{{>page}}');
}

@@ -12,4 +12,11 @@ import { ContractDefinition, SourceUnit } from 'solidity-ast';

export type PageAssigner = NonNullable<Config['pages']>;
export type PageStructure = NonNullable<Config['pages']>;
export type PageAssigner = Exclude<PageStructure, string>;
const pageAssigner: Record<PageStructure & string, PageAssigner> = {
single: () => 'index.md',
items: (item) => item.name,
};
export interface Site {

@@ -38,3 +45,5 @@ items: DocItemWithContext[];

export function buildSite(builds: Build[], assign: PageAssigner): Site {
export function buildSite(builds: Build[], pageStructure: PageStructure): Site {
const assign = typeof pageStructure === 'string' ? pageAssigner[pageStructure] : pageStructure;
const seen = new Set<string>();

@@ -41,0 +50,0 @@ const items: DocItemWithContext[] = [];

@@ -5,2 +5,3 @@ import { FunctionDefinition } from 'solidity-ast';

import { DocItemWithContext } from '../site';
import { arraysEqual } from './arrays-equal';
import { execAll } from './execall';

@@ -28,9 +29,12 @@ import { getContractsInScope } from './scope';

if (!item.__item_context) throw new Error(`Not an item or item is missing context`);
if (!('documentation' in item && item.documentation)) return {};
let res: NatSpec = {};
const docString = 'documentation' in item && item.documentation?.text
? cleanUpDocstring(item.documentation.text)
: '';
const tagMatches = execAll(
/^(?:@(\w+|custom:[a-z][a-z-]*) )?((?:(?!^@(?:\w+|custom:[a-z][a-z-]*) )[^])*)/m,
cleanUpDocstring(item.documentation.text),
docString,
);

@@ -99,6 +103,16 @@

}
inheritFrom = [...findAll('FunctionDefinition', parentContract)].find(f => f.name === item.name);
inheritFrom = [...findAll('FunctionDefinition', parentContract)].find(f => item.baseFunctions?.includes(f.id));
}
}
if (docString.length === 0) {
if ('baseFunctions' in item && item.baseFunctions?.length === 1) {
const baseFn = item.__item_context.build.deref('FunctionDefinition', item.baseFunctions[0]!);
const shouldInherit = item.nodeType === 'VariableDeclaration' || arraysEqual(item.parameters.parameters, baseFn.parameters.parameters, p => p.name);
if (shouldInherit) {
inheritFrom = baseFn;
}
}
}
if (res.dev) res.dev = res.dev.trim();

@@ -110,3 +124,2 @@ if (res.notice) res.notice = res.notice.trim();

}
// [TODO] inheritance by default as specified by solidity

@@ -113,0 +126,0 @@ return res;

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