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.7.1 to 0.7.2

4

CHANGELOG.md
# Changelog
## 0.7.2
- Add rule MULTIPLE_API_VERSION to validate if the default tag in readme.md contains multiple API version.
## 0.7.1

@@ -4,0 +8,0 @@

@@ -31,2 +31,5 @@ "use strict";

}
if (error.code === 'MULTIPLE_API_VERSION') {
return fileChanges.some(item => exports.hasCommonRPFolder(item.path, error.readMeUrl));
}
return false;

@@ -33,0 +36,0 @@ };

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.';
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.';
export interface IErrorBase {

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

} & IErrorBase;
export declare type MultipleApiVersion = {
readonly code: 'MULTIPLE_API_VERSION';
readonly message: ErrorMessage;
readonly readMeUrl: string;
readonly tag: string | undefined;
} & IErrorBase;
export declare type FileError = {

@@ -32,4 +38,4 @@ readonly code: 'NO_JSON_FILE_FOUND' | 'UNREFERENCED_JSON_FILE' | 'CIRCULAR_REFERENCE' | 'INCONSISTENT_API_VERSION';

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

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

];
case 'MULTIPLE_API_VERSION':
return [
{ tag: 'readme', path: format.blobHref(format.getRelativeSwaggerPathToRepo(error.readMeUrl)) },
{
tag: 'tag',
path: format.blobHref(format.getRelativeSwaggerPathToRepo(`${error.readMeUrl}#tag-${error.tag}`)),
},
];
case 'MISSING_README':

@@ -24,0 +32,0 @@ return [{ tag: 'folder', path: format.blobHref(format.getRelativeSwaggerPathToRepo(error.folderUrl)) }];

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

import * as md from '@ts-common/commonmark-to-markdown';
import * as asyncIt from '@ts-common/async-iterator';
import * as commonmark from 'commonmark';
import * as cli from './cli';

@@ -9,2 +11,11 @@ import * as git from './git';

/**
* @return return undefined indicates not found, otherwise return non-empty string.
*/
export declare const getDefaultTag: (markDown: commonmark.Node) => string | undefined;
/**
* @return return undefined indicates not found, otherwise return non-empty string.
*/
export declare const getVersionFromInputFile: (filePath: string) => string | undefined;
export declare const isContainsMultiVersion: (m: md.MarkDownEx) => boolean;
/**
* The function validates files in the given `cwd` folder and returns errors.

@@ -11,0 +22,0 @@ */

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

const err = tslib_1.__importStar(require("./errors"));
const YAML = tslib_1.__importStar(require("js-yaml"));
// tslint:disable-next-line: no-require-imports

@@ -62,2 +63,8 @@ const nodeObjectHash = require("node-object-hash");

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

@@ -89,2 +96,71 @@ };

});
const safeLoad = (content) => {
try {
return YAML.safeLoad(content);
}
catch (err) {
return undefined;
}
};
/**
* @return return undefined indicates not found, otherwise return non-empty string.
*/
exports.getDefaultTag = (markDown) => {
const startNode = markDown;
const codeBlockMap = openApiMd.getCodeBlocksAndHeadings(startNode);
const latestHeader = 'Basic Information';
const headerBlock = codeBlockMap[latestHeader];
if (headerBlock && headerBlock.literal) {
const latestDefinition = safeLoad(headerBlock.literal);
if (latestDefinition && latestDefinition.tag) {
return latestDefinition.tag;
}
}
for (const idx of Object.keys(codeBlockMap)) {
const block = codeBlockMap[idx];
if (!block || !block.info || !block.literal || !/^(yaml|json)$/.test(block.info.trim().toLowerCase())) {
continue;
}
const latestDefinition = safeLoad(block.literal);
if (latestDefinition && latestDefinition.tag) {
return latestDefinition.tag;
}
}
return undefined;
};
/**
* @return return undefined indicates not found, otherwise return non-empty string.
*/
exports.getVersionFromInputFile = (filePath) => {
const apiVersionRegex = /^\d{4}-\d{2}-\d{2}(|-preview)$/;
const segments = filePath.split('/').slice(0, -1);
if (segments && segments.length > 1) {
for (const s of segments) {
if (apiVersionRegex.test(s)) {
return s;
}
}
}
return undefined;
};
exports.isContainsMultiVersion = (m) => {
const defaultTag = exports.getDefaultTag(m.markDown);
if (!defaultTag) {
return false;
}
const inputFiles = openApiMd.getInputFilesForTag(m.markDown, defaultTag);
if (inputFiles) {
const versions = new Set();
for (const file of inputFiles) {
const version = exports.getVersionFromInputFile(file);
if (version) {
versions.add(version);
if (versions.size > 1) {
return true;
}
}
}
}
return false;
};
const jsonParse = (fileName, file) => {

@@ -263,2 +339,11 @@ // tslint:disable-next-line:readonly-array

}
if (exports.isContainsMultiVersion(m)) {
yield {
code: 'MULTIPLE_API_VERSION',
message: 'The default tag contains multiple API versions swaggers.',
readMeUrl: readMePath,
tag: exports.getDefaultTag(m.markDown),
level: 'Warning',
};
}
});

@@ -265,0 +350,0 @@ /**

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

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

@@ -113,2 +113,10 @@ # Avocado

### MULTIPLE_API_VERSION
Level: WARNING
The default tag should contain only one API version swagger.
To solve this warning , you should copy the swaggers of old version into the current version folder.
## Contributing

@@ -115,0 +123,0 @@

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

}
if (error.code === 'MULTIPLE_API_VERSION') {
return fileChanges.some(item => hasCommonRPFolder(item.path, error.readMeUrl))
}
return false

@@ -86,0 +89,0 @@ }

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

| 'The API version of the swagger is inconsistent with its file path.'
| 'The default tag contains multiple API versions swaggers.'

@@ -36,2 +37,9 @@ export interface IErrorBase {

export type MultipleApiVersion = {
readonly code: 'MULTIPLE_API_VERSION'
readonly message: ErrorMessage
readonly readMeUrl: string
readonly tag: string | undefined
} & IErrorBase
export type FileError = {

@@ -67,2 +75,10 @@ readonly code: 'NO_JSON_FILE_FOUND' | 'UNREFERENCED_JSON_FILE' | 'CIRCULAR_REFERENCE' | 'INCONSISTENT_API_VERSION'

]
case 'MULTIPLE_API_VERSION':
return [
{ tag: 'readme', path: format.blobHref(format.getRelativeSwaggerPathToRepo(error.readMeUrl)) },
{
tag: 'tag',
path: format.blobHref(format.getRelativeSwaggerPathToRepo(`${error.readMeUrl}#tag-${error.tag}`)),
},
]
case 'MISSING_README':

@@ -75,2 +91,2 @@ return [{ tag: 'folder', path: format.blobHref(format.getRelativeSwaggerPathToRepo(error.folderUrl)) }]

export type Error = JsonParseError | FileError | NotAutoRestMarkDown | MissingReadmeError
export type Error = JsonParseError | FileError | NotAutoRestMarkDown | MissingReadmeError | MultipleApiVersion

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

import * as format from '@azure/swagger-validation-common'
import * as YAML from 'js-yaml'

@@ -62,2 +63,8 @@ // tslint:disable-next-line: no-require-imports

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

@@ -95,2 +102,75 @@ }

const safeLoad = (content: string) => {
try {
return YAML.safeLoad(content)
} catch (err) {
return undefined
}
}
/**
* @return return undefined indicates not found, otherwise return non-empty string.
*/
export const getDefaultTag = (markDown: commonmark.Node): string | undefined => {
const startNode = markDown
const codeBlockMap = openApiMd.getCodeBlocksAndHeadings(startNode)
const latestHeader = 'Basic Information'
const headerBlock = codeBlockMap[latestHeader]
if (headerBlock && headerBlock.literal) {
const latestDefinition = safeLoad(headerBlock.literal)
if (latestDefinition && latestDefinition.tag) {
return latestDefinition.tag
}
}
for (const idx of Object.keys(codeBlockMap)) {
const block = codeBlockMap[idx]
if (!block || !block.info || !block.literal || !/^(yaml|json)$/.test(block.info.trim().toLowerCase())) {
continue
}
const latestDefinition = safeLoad(block.literal)
if (latestDefinition && latestDefinition.tag) {
return latestDefinition.tag
}
}
return undefined
}
/**
* @return return undefined indicates not found, otherwise return non-empty string.
*/
export const getVersionFromInputFile = (filePath: string): string | undefined => {
const apiVersionRegex = /^\d{4}-\d{2}-\d{2}(|-preview)$/
const segments = filePath.split('/').slice(0, -1)
if (segments && segments.length > 1) {
for (const s of segments) {
if (apiVersionRegex.test(s)) {
return s
}
}
}
return undefined
}
export const isContainsMultiVersion = (m: md.MarkDownEx): boolean => {
const defaultTag = getDefaultTag(m.markDown)
if (!defaultTag) {
return false
}
const inputFiles = openApiMd.getInputFilesForTag(m.markDown, defaultTag)
if (inputFiles) {
const versions = new Set<string>()
for (const file of inputFiles) {
const version = getVersionFromInputFile(file)
if (version) {
versions.add(version)
if (versions.size > 1) {
return true
}
}
}
}
return false
}
const jsonParse = (fileName: string, file: string) => {

@@ -328,2 +408,11 @@ // tslint:disable-next-line:readonly-array

}
if (isContainsMultiVersion(m)) {
yield {
code: 'MULTIPLE_API_VERSION',
message: 'The default tag contains multiple API versions swaggers.',
readMeUrl: readMePath,
tag: getDefaultTag(m.markDown),
level: 'Warning',
}
}
})

@@ -330,0 +419,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

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