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

@azure/avocado

Package Overview
Dependencies
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@azure/avocado - npm Package Compare versions

Comparing version 0.8.7 to 0.8.8

13

bin/cli.js

@@ -13,4 +13,9 @@ #!/usr/bin/env node

type: 'array',
desc: 'array contains path patterns to be ignored'
desc: 'array contains path patterns to be ignored',
})
.option('includePaths', {
type: 'array',
desc:
'array contains path patterns to be included. If this option is not set, all files will be included. If this option is set, only files that match at least one pattern will be included',
})
.help('h')

@@ -21,2 +26,6 @@ .alias('h', 'help').argv

cli.run(index.avocado, index.UnifiedPipelineReport(argv.f), {cwd: process.cwd(), env: process.env, args: {dir: argv.d, excludePaths: argv.excludePaths}})
cli.run(index.avocado, index.UnifiedPipelineReport(argv.f), {
cwd: process.cwd(),
env: process.env,
args: { dir: argv.d, excludePaths: argv.excludePaths, includePaths: argv.includePaths },
})

10

dist/errors.d.ts
import { JsonParseError } from './errors';
import * as jsonParser from '@ts-common/json-parser';
import * as format from '@azure/swagger-validation-common';
declare type ErrorMessage = 'The example JSON file is not referenced from the swagger file.' | 'The swagger JSON file is not referenced from the readme file.' | 'The `readme.md` is not an AutoRest markdown file.' | 'The JSON file is not found but it is referenced from the readme file.' | 'The JSON file has a circular reference.' | 'The file is not a valid JSON file.' | 'Can not find readme.md in the folder. If no readme.md file, it will block SDK generation.' | 'The API version of the swagger is inconsistent with its file path.' | 'The default tag contains multiple API versions swaggers.' | 'The management plane swagger JSON file does not match its folder path. Make sure management plane swagger located in resource-manager folder' | 'The default tag does not contain all APIs in this RP. Please make sure the missing API swaggers are in the default tag.' | 'The default tag does not contains the latest API version. Please make sure the latest api version swaggers are in the default tag.';
declare type ErrorMessage = 'The example JSON file is not referenced from the swagger file.' | 'The swagger JSON file is not referenced from the readme file.' | 'The `readme.md` is not an AutoRest markdown file.' | 'The JSON file is not found but it is referenced from the readme file.' | 'The JSON file has a circular reference.' | 'The file is not a valid JSON file.' | 'Can not find readme.md in the folder. If no readme.md file, it will block SDK generation.' | 'The API version of the swagger is inconsistent with its file path.' | 'The default tag contains multiple API versions swaggers.' | 'The management plane swagger JSON file does not match its folder path. Make sure management plane swagger located in resource-manager folder' | 'The default tag does not contain all APIs in this RP. Please make sure the missing API swaggers are in the default tag.' | 'The default tag does not contains the latest API version. Please make sure the latest api version swaggers are in the default tag.' | 'The readme file has more than one default tag.';
export interface IErrorBase {

@@ -26,2 +26,8 @@ readonly level: 'Warning' | 'Error' | 'Info';

} & IErrorBase;
export declare type MultipleDefaultTags = {
readonly code: 'MULTIPLE_DEFAULT_TAGS';
readonly message: ErrorMessage;
readonly readMeUrl: string;
readonly tags: string[];
} & IErrorBase;
export declare type MissingLatestApiInDefaultTag = {

@@ -46,4 +52,4 @@ readonly code: 'MISSING_APIS_IN_DEFAULT_TAG' | 'NOT_LATEST_API_VERSION_IN_DEFAULT_TAG';

export declare const getPathInfoFromError: (error: Error) => format.JsonPath[];
export declare type Error = JsonParseError | FileError | NotAutoRestMarkDown | MissingReadmeError | MultipleApiVersion | MissingLatestApiInDefaultTag;
export declare type Error = JsonParseError | FileError | NotAutoRestMarkDown | MissingReadmeError | MultipleApiVersion | MissingLatestApiInDefaultTag | MultipleDefaultTags;
export {};
//# sourceMappingURL=errors.d.ts.map

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

{ tag: 'json', path: format.blobHref(format.getRelativeSwaggerPathToRepo(error.jsonUrl)) },
{ tag: 'path', path: error.path },
];

@@ -43,2 +44,4 @@ case 'NOT_LATEST_API_VERSION_IN_DEFAULT_TAG':

];
case 'MULTIPLE_DEFAULT_TAGS':
return [{ tag: 'readme', path: format.blobHref(format.getRelativeSwaggerPathToRepo(error.readMeUrl)) }];
default:

@@ -45,0 +48,0 @@ return [];

@@ -12,2 +12,6 @@ import * as md from '@ts-common/commonmark-to-markdown';

/**
* @return return tag string array.
*/
export declare const getAllDefaultTags: (markDown: commonmark.Node) => string[];
/**
* @return return undefined indicates not found, otherwise return non-empty string.

@@ -14,0 +18,0 @@ */

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

readMeUrl: error.readMeUrl,
path: error.path,
};

@@ -92,2 +93,9 @@ }

}
case 'MULTIPLE_DEFAULT_TAGS': {
return {
code: error.code,
url: error.readMeUrl,
tags: error.tags,
};
}
}

@@ -127,3 +135,53 @@ };

};
const nodeHeading = (startNode) => {
let resultNode = startNode;
while (resultNode !== null && resultNode.type !== 'heading') {
resultNode = resultNode.prev || resultNode.parent;
}
return resultNode;
};
const getHeadingLiteral = (heading) => {
const headingNode = walkToNode(heading.walker(), n => n.type === 'text');
return headingNode && headingNode.literal ? headingNode.literal : '';
};
/**
* walks a markdown tree until the callback provided returns true for a node
*/
const walkToNode = (walker, cb) => {
let event = walker.next();
while (event) {
const curNode = event.node;
if (cb(curNode)) {
return curNode;
}
event = walker.next();
}
return undefined;
};
/**
* @return return tag string array.
*/
exports.getAllDefaultTags = (markDown) => {
const startNode = markDown;
const walker = startNode.walker();
const tags = [];
while (true) {
const node = walkToNode(walker, n => n.type === 'code_block');
if (!node) {
break;
}
const heading = nodeHeading(node);
if (!heading) {
continue;
}
if (getHeadingLiteral(heading) === 'Basic Information' && node.literal) {
const latestDefinition = safeLoad(node.literal);
if (latestDefinition && latestDefinition.tag) {
tags.push(latestDefinition.tag);
}
}
}
return tags;
};
/**
* @return return undefined indicates not found, otherwise return non-empty string.

@@ -294,2 +352,14 @@ */

const m = md.parse(readmeContent);
const defaultTags = exports.getAllDefaultTags(m.markDown);
if (defaultTags.length > 1) {
yield {
code: 'MULTIPLE_DEFAULT_TAGS',
level: 'Warning',
message: 'The readme file has more than one default tag.',
path: readme,
readMeUrl: readme,
tags: defaultTags,
};
continue;
}
const inputFiles = exports.getSwaggerFileUnderDefaultTag(m);

@@ -648,3 +718,3 @@ let defaultTagPathTable = new Map();

*/
const avocadoForDir = async (dir, exclude) => {
const avocadoForDir = async (dir, exclude, include) => {
const map = new Map();

@@ -658,3 +728,4 @@ if (fs.existsSync(dir)) {

for (const [k, v] of map) {
if (exclude.some(item => v.path.search(item) !== -1)) {
if ((include.length > 0 && include.every(item => v.path.search(item) === -1)) ||
exclude.some(item => v.path.search(item) !== -1)) {
map.delete(k);

@@ -671,3 +742,3 @@ }

*/
const avocadoForDevOps = (pr, exclude) => asyncIt.iterable(async function* () {
const avocadoForDevOps = (pr, exclude, include) => asyncIt.iterable(async function* () {
// collect all errors from the 'targetBranch'

@@ -699,6 +770,6 @@ const diffFiles = await pr.diff();

await pr.checkout(pr.targetBranch);
const targetMap = await avocadoForDir(path.resolve(pr.workingDir, dir), exclude);
const targetMap = await avocadoForDir(path.resolve(pr.workingDir, dir), exclude, include);
// collect all errors from the 'sourceBranch'
await pr.checkout(pr.sourceBranch);
const sourceMap = await avocadoForDir(path.resolve(pr.workingDir, dir), exclude);
const sourceMap = await avocadoForDir(path.resolve(pr.workingDir, dir), exclude, include);
const fileChanges = await pr.diff();

@@ -727,4 +798,8 @@ // remove existing errors.

}
let include = [];
if (config.args && config.args.includePaths) {
include = config.args.includePaths;
}
if (pr !== undefined) {
yield* avocadoForDevOps(pr, exclude);
yield* avocadoForDevOps(pr, exclude, include);
}

@@ -737,3 +812,3 @@ else {

}
yield* (await avocadoForDir(path.resolve(config.cwd, dir), exclude)).values();
yield* (await avocadoForDir(path.resolve(config.cwd, dir), exclude, include)).values();
}

@@ -740,0 +815,0 @@ });

{
"name": "@azure/avocado",
"version": "0.8.7",
"version": "0.8.8",
"description": "A validator of OpenAPI configurations",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -24,2 +24,3 @@ import { JsonParseError } from './errors'

| 'The default tag does not contains the latest API version. Please make sure the latest api version swaggers are in the default tag.'
| 'The readme file has more than one default tag.'

@@ -51,2 +52,9 @@ export interface IErrorBase {

export type MultipleDefaultTags = {
readonly code: 'MULTIPLE_DEFAULT_TAGS'
readonly message: ErrorMessage
readonly readMeUrl: string
readonly tags: string[]
} & IErrorBase
export type MissingLatestApiInDefaultTag = {

@@ -110,2 +118,3 @@ readonly code: 'MISSING_APIS_IN_DEFAULT_TAG' | 'NOT_LATEST_API_VERSION_IN_DEFAULT_TAG'

{ tag: 'json', path: format.blobHref(format.getRelativeSwaggerPathToRepo(error.jsonUrl)) },
{ tag: 'path', path: error.path },
]

@@ -117,2 +126,4 @@ case 'NOT_LATEST_API_VERSION_IN_DEFAULT_TAG':

]
case 'MULTIPLE_DEFAULT_TAGS':
return [{ tag: 'readme', path: format.blobHref(format.getRelativeSwaggerPathToRepo(error.readMeUrl)) }]
default:

@@ -130,1 +141,2 @@ return []

| MissingLatestApiInDefaultTag
| MultipleDefaultTags

@@ -82,2 +82,3 @@ // Copyright (c) Microsoft Corporation. All rights reserved.

readMeUrl: error.readMeUrl,
path: error.path,
}

@@ -92,2 +93,9 @@ }

}
case 'MULTIPLE_DEFAULT_TAGS': {
return {
code: error.code,
url: error.readMeUrl,
tags: error.tags,
}
}
}

@@ -133,3 +141,64 @@ }

const nodeHeading = (startNode: commonmark.Node): commonmark.Node | null => {
let resultNode: commonmark.Node | null = startNode
while (resultNode !== null && resultNode.type !== 'heading') {
resultNode = resultNode.prev || resultNode.parent
}
return resultNode
}
const getHeadingLiteral = (heading: commonmark.Node): string => {
const headingNode = walkToNode(heading.walker(), n => n.type === 'text')
return headingNode && headingNode.literal ? headingNode.literal : ''
}
/**
* walks a markdown tree until the callback provided returns true for a node
*/
const walkToNode = (
walker: commonmark.NodeWalker,
cb: (node: commonmark.Node) => boolean,
): commonmark.Node | undefined => {
let event = walker.next()
while (event) {
const curNode = event.node
if (cb(curNode)) {
return curNode
}
event = walker.next()
}
return undefined
}
/**
* @return return tag string array.
*/
export const getAllDefaultTags = (markDown: commonmark.Node): string[] => {
const startNode = markDown
const walker = startNode.walker()
const tags = []
while (true) {
const node = walkToNode(walker, n => n.type === 'code_block')
if (!node) {
break
}
const heading = nodeHeading(node)
if (!heading) {
continue
}
if (getHeadingLiteral(heading) === 'Basic Information' && node.literal) {
const latestDefinition = safeLoad(node.literal)
if (latestDefinition && latestDefinition.tag) {
tags.push(latestDefinition.tag)
}
}
}
return tags
}
/**
* @return return undefined indicates not found, otherwise return non-empty string.

@@ -347,2 +416,15 @@ */

const m = md.parse(readmeContent)
const defaultTags = getAllDefaultTags(m.markDown)
if (defaultTags.length > 1) {
yield {
code: 'MULTIPLE_DEFAULT_TAGS',
level: 'Warning',
message: 'The readme file has more than one default tag.',
path: readme,
readMeUrl: readme,
tags: defaultTags,
}
continue
}
const inputFiles = getSwaggerFileUnderDefaultTag(m)

@@ -752,3 +834,3 @@ let defaultTagPathTable = new Map<string, { apiVersion: string; swaggerFile: string }>()

*/
const avocadoForDir = async (dir: string, exclude: string[]) => {
const avocadoForDir = async (dir: string, exclude: string[], include: string[]) => {
const map = new Map<string, err.Error>()

@@ -762,3 +844,6 @@ if (fs.existsSync(dir)) {

for (const [k, v] of map) {
if (exclude.some(item => v.path.search(item) !== -1)) {
if (
(include.length > 0 && include.every(item => v.path.search(item) === -1)) ||
exclude.some(item => v.path.search(item) !== -1)
) {
map.delete(k)

@@ -776,3 +861,7 @@ }

*/
const avocadoForDevOps = (pr: devOps.PullRequestProperties, exclude: string[]): asyncIt.AsyncIterableEx<err.Error> =>
const avocadoForDevOps = (
pr: devOps.PullRequestProperties,
exclude: string[],
include: string[],
): asyncIt.AsyncIterableEx<err.Error> =>
asyncIt.iterable<err.Error>(async function*() {

@@ -806,7 +895,7 @@ // collect all errors from the 'targetBranch'

await pr.checkout(pr.targetBranch)
const targetMap = await avocadoForDir(path.resolve(pr.workingDir, dir), exclude)
const targetMap = await avocadoForDir(path.resolve(pr.workingDir, dir), exclude, include)
// collect all errors from the 'sourceBranch'
await pr.checkout(pr.sourceBranch)
const sourceMap = await avocadoForDir(path.resolve(pr.workingDir, dir), exclude)
const sourceMap = await avocadoForDir(path.resolve(pr.workingDir, dir), exclude, include)

@@ -840,4 +929,8 @@ const fileChanges = await pr.diff()

}
let include = []
if (config.args && config.args.includePaths) {
include = config.args.includePaths
}
if (pr !== undefined) {
yield* avocadoForDevOps(pr, exclude)
yield* avocadoForDevOps(pr, exclude, include)
} else {

@@ -849,3 +942,3 @@ // tslint:disable-next-line: no-let

}
yield* (await avocadoForDir(path.resolve(config.cwd, dir), exclude)).values()
yield* (await avocadoForDir(path.resolve(config.cwd, dir), exclude, include)).values()
}

@@ -852,0 +945,0 @@ })

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