@definitelytyped/header-parser
Advanced tools
Comparing version 0.0.178 to 0.0.179
@@ -1,31 +0,34 @@ | ||
import pm = require("parsimmon"); | ||
import { AllTypeScriptVersion, TypeScriptVersion } from "@definitelytyped/typescript-versions"; | ||
export interface Header { | ||
readonly nonNpm: boolean; | ||
readonly libraryName: string; | ||
readonly nonNpmDescription?: string; | ||
readonly name: string; | ||
readonly libraryMajorVersion: number; | ||
readonly libraryMinorVersion: number; | ||
readonly typeScriptVersion: AllTypeScriptVersion; | ||
readonly minimumTypeScriptVersion: AllTypeScriptVersion; | ||
readonly projects: readonly string[]; | ||
readonly contributors: readonly Author[]; | ||
readonly owners: readonly Owner[]; | ||
} | ||
export interface Author { | ||
export type Owner = { | ||
readonly name: string; | ||
readonly url: string; | ||
readonly githubUsername: string | undefined; | ||
} | { | ||
readonly name: string; | ||
readonly githubUsername: string; | ||
readonly url?: undefined; | ||
}; | ||
export declare function makeTypesVersionsForPackageJson(typesVersions: readonly AllTypeScriptVersion[]): unknown; | ||
export declare function validatePackageJson(typesDirectoryName: string, packageJson: Record<string, unknown>, typesVersions: readonly AllTypeScriptVersion[]): Header | string[]; | ||
export declare function getTypesVersions(dirPath: string): readonly TypeScriptVersion[]; | ||
export declare const enum License { | ||
MIT = "MIT", | ||
Apache20 = "Apache-2.0" | ||
} | ||
export interface ParseError { | ||
readonly index: number; | ||
readonly line: number; | ||
readonly column: number; | ||
readonly expected: readonly string[]; | ||
} | ||
export declare function makeTypesVersionsForPackageJson(typesVersions: readonly TypeScriptVersion[]): unknown; | ||
export declare function parseHeaderOrFail(descriptor: string, mainFileContent: string): Header; | ||
export declare function validate(mainFileContent: string): ParseError | undefined; | ||
export declare function renderExpected(expected: readonly string[]): string; | ||
export declare function parseTypeScriptVersionLine(line: string): AllTypeScriptVersion; | ||
declare module "parsimmon" { | ||
type Pr<T> = pm.Parser<T>; | ||
function seqMap<T, U, V, W, X, Y, Z, A, B, C>(p1: Pr<T>, p2: Pr<U>, p3: Pr<V>, p4: Pr<W>, p5: Pr<X>, p6: Pr<Y>, p7: Pr<Z>, p8: Pr<A>, p9: Pr<B>, cb: (a1: T, a2: U, a3: V, a4: W, a5: X, a6: Y, a7: Z, a8: A, a9: B) => C): Pr<C>; | ||
} | ||
export declare function getLicenseFromPackageJson(packageJsonLicense: unknown): License | string[]; | ||
export declare function checkPackageJsonExportsAndAddPJsonEntry(exports: unknown, path: string): string | object | undefined; | ||
export declare function checkPackageJsonImports(imports: unknown, path: string): object | string[] | undefined; | ||
export declare function checkPackageJsonType(type: unknown, path: string): string[] | "module" | undefined; | ||
/** | ||
* @param devDependencySelfName - pass the package name only for devDependencies | ||
*/ | ||
export declare function checkPackageJsonDependencies(dependencies: unknown, path: string, allowedDependencies: ReadonlySet<string>, devDependencySelfName?: string): string[]; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (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; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.parseTypeScriptVersionLine = exports.renderExpected = exports.validate = exports.parseHeaderOrFail = exports.makeTypesVersionsForPackageJson = void 0; | ||
const pm = require("parsimmon"); | ||
exports.checkPackageJsonDependencies = exports.checkPackageJsonType = exports.checkPackageJsonImports = exports.checkPackageJsonExportsAndAddPJsonEntry = exports.getLicenseFromPackageJson = exports.getTypesVersions = exports.validatePackageJson = exports.makeTypesVersionsForPackageJson = void 0; | ||
const typescript_versions_1 = require("@definitelytyped/typescript-versions"); | ||
const assert = require("assert"); | ||
const fs = require("fs"); | ||
const semver = __importStar(require("semver")); | ||
const utils_1 = require("@definitelytyped/utils"); | ||
function makeTypesVersionsForPackageJson(typesVersions) { | ||
@@ -19,174 +45,410 @@ if (typesVersions.length === 0) { | ||
exports.makeTypesVersionsForPackageJson = makeTypesVersionsForPackageJson; | ||
function parseHeaderOrFail(descriptor, mainFileContent) { | ||
const header = parseHeader(mainFileContent, /*strict*/ false); | ||
if (isParseError(header)) { | ||
throw new Error(renderParseError(descriptor, header)); | ||
function validatePackageJson(typesDirectoryName, packageJson, typesVersions) { | ||
const errors = []; | ||
const needsTypesVersions = typesVersions.length !== 0; | ||
for (const key in packageJson) { | ||
switch (key) { | ||
case "private": | ||
case "dependencies": | ||
case "license": | ||
case "imports": | ||
case "exports": | ||
case "type": | ||
case "name": | ||
case "version": | ||
case "devDependencies": | ||
case "projects": | ||
case "minimumTypeScriptVersion": | ||
case "owners": | ||
case "nonNpm": | ||
case "nonNpmDescription": | ||
case "pnpm": | ||
break; | ||
case "typesVersions": | ||
case "types": | ||
if (!needsTypesVersions) { | ||
errors.push(`${typesDirectoryName}'s package.json doesn't need to set "${key}" when no 'tsX.X' directories exist.`); | ||
} | ||
break; | ||
default: | ||
errors.push(`${typesDirectoryName}'s package.json should not include property ${key}`); | ||
} | ||
} | ||
return header; | ||
} | ||
exports.parseHeaderOrFail = parseHeaderOrFail; | ||
function validate(mainFileContent) { | ||
const h = parseHeader(mainFileContent, /*strict*/ true); | ||
return isParseError(h) ? h : undefined; | ||
} | ||
exports.validate = validate; | ||
function renderExpected(expected) { | ||
return expected.length === 1 ? expected[0] : `one of\n\t${expected.join("\n\t")}`; | ||
} | ||
exports.renderExpected = renderExpected; | ||
function renderParseError(descriptor, { line, column, expected }) { | ||
return `At ${line}:${column} in ${descriptor}: Expected ${renderExpected(expected)}`; | ||
} | ||
function isParseError(x) { | ||
// tslint:disable-next-line strict-type-predicates | ||
return x.expected !== undefined; | ||
} | ||
/** @param strict If true, we allow fewer things to be parsed. Turned on by linting. */ | ||
function parseHeader(text, strict) { | ||
const res = headerParser(strict).parse(text); | ||
return res.status | ||
? res.value | ||
: { index: res.index.offset, line: res.index.line, column: res.index.column, expected: res.expected }; | ||
} | ||
function headerParser(strict) { | ||
return pm.seqMap(pm.regex(/\/\/ Type definitions for (non-npm package )?/), parseLabel(strict), pm.string("// Project: "), projectParser, pm.regexp(/\r?\n\/\/ Definitions by: /), contributorsParser(strict), definitionsParser, typeScriptVersionParser, pm.all, // Don't care about the rest of the file | ||
// tslint:disable-next-line:variable-name | ||
(str, label, _project, projects, _defsBy, contributors, _definitions, typeScriptVersion) => ({ | ||
libraryName: label.name, | ||
libraryMajorVersion: label.major, | ||
libraryMinorVersion: label.minor, | ||
nonNpm: str.endsWith("non-npm package "), | ||
projects, | ||
contributors, | ||
typeScriptVersion, | ||
})); | ||
} | ||
/* | ||
Allow any of the following: | ||
// Project: https://foo.com | ||
// https://bar.com | ||
// Project: https://foo.com, | ||
// https://bar.com | ||
// Project: https://foo.com, https://bar.com | ||
Use `\s\s+` to ensure at least 2 spaces, to disambiguate from the next line being `// Definitions by:`. | ||
*/ | ||
const separator = pm.regexp(/(, )|(,?\r?\n\/\/\s\s+)/); | ||
const projectParser = pm.sepBy1(pm.regexp(/[^,\r\n]+/), separator); | ||
function contributorsParser(strict) { | ||
const contributor = strict | ||
? pm.seqMap(pm.regexp(/([^<]+) /, 1), pm.regexp(/\<https\:\/\/github\.com\/([a-zA-Z\d\-]+)\/?\>/, 1), (name, githubUsername) => ({ name, url: `https://github.com/${githubUsername}`, githubUsername })) | ||
: // In non-strict mode, allows arbitrary URL, and trailing whitespace. | ||
pm.seqMap(pm.regexp(/([^<]+) /, 1), pm.regexp(/<([^>]+)> */, 1), (name, url) => { | ||
const rgx = /^https\:\/\/github.com\/([a-zA-Z\d\-]+)\/?$/; | ||
const match = rgx.exec(url); | ||
const githubUsername = match === null ? undefined : match[1]; | ||
// tslint:disable-next-line no-null-keyword | ||
return { name, url: githubUsername ? `https://github.com/${githubUsername}` : url, githubUsername }; | ||
}); | ||
return pm.sepBy1(contributor, separator); | ||
} | ||
const definitionsParser = pm.regexp(/\r?\n\/\/ Definitions: [^\r\n]+/); | ||
function parseLabel(strict) { | ||
return pm.Parser((input, index) => { | ||
// Take all until the first newline. | ||
const endIndex = regexpIndexOf(input, /\r|\n/, index); | ||
if (endIndex === -1) { | ||
return fail("EOF"); | ||
// private | ||
if (packageJson.private !== true) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "private": must be \`"private": true\``); | ||
} | ||
// devDependencies | ||
if (typeof packageJson.devDependencies !== "object" || | ||
packageJson.devDependencies === null || | ||
packageJson.devDependencies["@types/" + typesDirectoryName] !== "workspace:.") { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "devDependencies": must include \`"@types/${typesDirectoryName}": "workspace:."\``); | ||
} | ||
// typesVersions | ||
if (needsTypesVersions) { | ||
assert.strictEqual(packageJson.types, "index", `"types" in '${typesDirectoryName}'s package.json' should be "index".`); | ||
const expected = makeTypesVersionsForPackageJson(typesVersions); | ||
if (!(0, utils_1.deepEquals)(packageJson.typesVersions, expected)) { | ||
errors.push(`'${typesDirectoryName}'s package.json' has bad "typesVersions". Should be: ${JSON.stringify(expected, undefined, 4)}`); | ||
} | ||
// Index past the end of the newline. | ||
const end = input[endIndex] === "\r" ? endIndex + 2 : endIndex + 1; | ||
const tilNewline = input.slice(index, endIndex); | ||
// Parse in reverse. Once we've stripped off the version, the rest is the libary name. | ||
const reversed = reverse(tilNewline); | ||
// Last digit is allowed to be "x", which acts like "0" | ||
const rgx = /((\d+|x)\.(\d+)(\.\d+)?(v)? )?(.+)/; | ||
const match = rgx.exec(reversed); | ||
if (match === null) { | ||
// tslint:disable-line no-null-keyword | ||
return fail(); | ||
} | ||
// building the header object uses a monadic error pattern based on the one in the old header parser | ||
// It's verbose and repetitive, but I didn't feel like writing a monadic `seq` to be used in only one place. | ||
let name = "ERROR"; | ||
let libraryMajorVersion = 0; | ||
let libraryMinorVersion = 0; | ||
let nonNpm = false; | ||
let minimumTypeScriptVersion = typescript_versions_1.TypeScriptVersion.lowest; | ||
let projects = []; | ||
let owners = []; | ||
const nameResult = validateName(); | ||
const versionResult = validateVersion(); | ||
const nonNpmResult = validateNonNpm(); | ||
const typeScriptVersionResult = validateTypeScriptVersion(); | ||
const projectsResult = validateProjects(); | ||
const ownersResult = validateOwners(); | ||
const pnpmResult = validatePnpm(); | ||
const licenseResult = getLicenseFromPackageJson(packageJson.license); | ||
if (typeof nameResult === "object") { | ||
errors.push(...nameResult.errors); | ||
} | ||
else { | ||
name = packageJson.name; | ||
} | ||
if ("errors" in versionResult) { | ||
errors.push(...versionResult.errors); | ||
} | ||
else { | ||
libraryMajorVersion = versionResult.major; | ||
libraryMinorVersion = versionResult.minor; | ||
} | ||
if (typeof nonNpmResult === "object") { | ||
errors.push(...nonNpmResult.errors); | ||
} | ||
else { | ||
nonNpm = nonNpmResult; | ||
} | ||
if (typeof typeScriptVersionResult === "object") { | ||
errors.push(...typeScriptVersionResult.errors); | ||
} | ||
else { | ||
minimumTypeScriptVersion = typeScriptVersionResult; | ||
} | ||
if ("errors" in projectsResult) { | ||
errors.push(...projectsResult.errors); | ||
} | ||
else { | ||
projects = projectsResult; | ||
} | ||
if ("errors" in ownersResult) { | ||
errors.push(...ownersResult.errors); | ||
} | ||
else { | ||
owners = ownersResult; | ||
} | ||
if (typeof pnpmResult === "object") { | ||
errors.push(...pnpmResult.errors); | ||
} | ||
if (Array.isArray(licenseResult)) { | ||
errors.push(...licenseResult); | ||
} | ||
if (errors.length) { | ||
return errors; | ||
} | ||
else { | ||
return { | ||
name, | ||
libraryMajorVersion, | ||
libraryMinorVersion, | ||
nonNpm, | ||
minimumTypeScriptVersion, | ||
projects, | ||
owners, | ||
}; | ||
} | ||
function validateName() { | ||
if (packageJson.name !== "@types/" + typesDirectoryName) { | ||
return { | ||
errors: [`${typesDirectoryName}'s package.json should have \`"name": "@types/${typesDirectoryName}"\``], | ||
}; | ||
} | ||
const [, version, a, b, c, v, nameReverse] = match; | ||
let majorReverse; | ||
let minorReverse; | ||
if (version !== undefined) { | ||
// tslint:disable-line strict-type-predicates | ||
if (c !== undefined) { | ||
// tslint:disable-line strict-type-predicates | ||
// There is a patch version | ||
majorReverse = c; | ||
minorReverse = b; | ||
if (strict) { | ||
return fail("patch version not allowed"); | ||
} | ||
else { | ||
return typesDirectoryName; | ||
} | ||
} | ||
function validateVersion() { | ||
const errors = []; | ||
if (!packageJson.version || typeof packageJson.version !== "string") { | ||
errors.push(`${typesDirectoryName}'s package.json should have \`"version"\` matching the version of the implementation package.`); | ||
} | ||
else { | ||
const version = semver.parse(packageJson.version); | ||
if (version === null) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "version": ${JSON.stringify(packageJson.version)} should look like "NN.NN.9999"`); | ||
} | ||
else if (version.patch !== 9999) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "version": ${version} must end with ".9999"`); | ||
} | ||
else { | ||
majorReverse = b; | ||
minorReverse = a; | ||
return { major: version.major, minor: version.minor }; | ||
} | ||
if (v !== undefined && strict) { | ||
// tslint:disable-line strict-type-predicates | ||
return fail("'v' not allowed"); | ||
} | ||
return { errors }; | ||
} | ||
function validateNonNpm() { | ||
const errors = []; | ||
if (packageJson.nonNpm !== undefined) { | ||
if (packageJson.nonNpm !== true) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "nonNpm": must be true if present.`); | ||
} | ||
else if (!packageJson.nonNpmDescription) { | ||
errors.push(`${typesDirectoryName}'s package.json has missing "nonNpmDescription", which is required with "nonNpm": true.`); | ||
} | ||
else if (typeof packageJson.nonNpmDescription !== "string") { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "nonNpmDescription": must be a string if present.`); | ||
} | ||
else { | ||
return true; | ||
} | ||
return { errors }; | ||
} | ||
else if (packageJson.nonNpmDescription !== undefined) { | ||
errors.push(`${typesDirectoryName}'s package.json has "nonNpmDescription" without "nonNpm": true.`); | ||
} | ||
if (errors.length) { | ||
return { errors }; | ||
} | ||
else { | ||
if (strict) { | ||
return fail("Needs MAJOR.MINOR"); | ||
return false; | ||
} | ||
} | ||
function validateTypeScriptVersion() { | ||
if (packageJson.minimumTypeScriptVersion) { | ||
if (typeof packageJson.minimumTypeScriptVersion !== "string" || | ||
!typescript_versions_1.TypeScriptVersion.isTypeScriptVersion(packageJson.minimumTypeScriptVersion)) { | ||
return { | ||
errors: [ | ||
`${typesDirectoryName}'s package.json has bad "minimumTypeScriptVersion": if present, must be a MAJOR.MINOR semver string up to "${typescript_versions_1.TypeScriptVersion.latest}". | ||
(Defaults to "${typescript_versions_1.TypeScriptVersion.lowest}" if not provided.)`, | ||
], | ||
}; | ||
} | ||
majorReverse = "0"; | ||
minorReverse = "0"; | ||
else { | ||
return packageJson.minimumTypeScriptVersion; | ||
} | ||
} | ||
const [name, major, minor] = [reverse(nameReverse), reverse(majorReverse), reverse(minorReverse)]; | ||
return pm.makeSuccess(end, { | ||
name, | ||
major: intOfString(major), | ||
minor: minor === "x" ? 0 : intOfString(minor), | ||
}); | ||
function fail(msg) { | ||
let expected = "foo MAJOR.MINOR"; | ||
if (msg !== undefined) { | ||
expected += ` (${msg})`; | ||
return typescript_versions_1.TypeScriptVersion.lowest; | ||
} | ||
function validateProjects() { | ||
const errors = []; | ||
if (!packageJson.projects || | ||
!Array.isArray(packageJson.projects) || | ||
!packageJson.projects.every((p) => typeof p === "string")) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "projects": must be an array of strings that point to the project web site(s).`); | ||
} | ||
else if (packageJson.projects.length === 0) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "projects": must have at least one project URL.`); | ||
} | ||
else { | ||
return packageJson.projects; | ||
} | ||
return { errors }; | ||
} | ||
function validateOwners() { | ||
const errors = []; | ||
if (!packageJson.owners || !Array.isArray(packageJson.owners)) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "owners": must be an array of type Array<{ name: string, url: string, githubUsername: string}>.`); | ||
} | ||
else { | ||
const es = checkPackageJsonOwners(typesDirectoryName, packageJson.owners); | ||
if (es.length) { | ||
errors.push(...es); | ||
} | ||
return pm.makeFailure(index, expected); | ||
else { | ||
return packageJson.owners; | ||
} | ||
} | ||
return { errors }; | ||
} | ||
function validatePnpm() { | ||
const errors = []; | ||
if (packageJson.pnpm) { | ||
if (typeof packageJson.pnpm !== "object" || packageJson.pnpm === null) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "pnpm": must be an object like { "overrides": { "@types/react": "^16" } }`); | ||
} | ||
else { | ||
for (const key in packageJson.pnpm) { | ||
if (key !== "overrides") { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "pnpm": it should not include property "${key}", only "overrides".`); | ||
} | ||
} | ||
const overrides = packageJson.pnpm.overrides; | ||
if (overrides && typeof overrides === "object" && overrides !== null) { | ||
for (const key in overrides) { | ||
if (!key.startsWith("@types/")) { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "pnpm": pnpm overrides may only override @types/ packages.`); | ||
} | ||
} | ||
} | ||
else { | ||
errors.push(`${typesDirectoryName}'s package.json has bad "pnpm": it must contain an "overrides" object.`); | ||
} | ||
} | ||
} | ||
if (errors.length) { | ||
return { errors }; | ||
} | ||
return undefined; | ||
} | ||
} | ||
exports.validatePackageJson = validatePackageJson; | ||
function getTypesVersions(dirPath) { | ||
return (0, utils_1.mapDefined)(fs.readdirSync(dirPath), (name) => { | ||
if (name === "tsconfig.json" || name === "tslint.json" || name === "tsutils") { | ||
return undefined; | ||
} | ||
const version = (0, utils_1.withoutStart)(name, "ts"); | ||
if (version === undefined || !fs.statSync((0, utils_1.joinPaths)(dirPath, name)).isDirectory()) { | ||
return undefined; | ||
} | ||
if (!typescript_versions_1.TypeScriptVersion.isTypeScriptVersion(version)) { | ||
throw new Error(`There is an entry named ${name}, but ${version} is not a valid TypeScript version.`); | ||
} | ||
if (!typescript_versions_1.TypeScriptVersion.isSupported(version)) { | ||
throw new Error(`At ${dirPath}/${name}: TypeScript version ${version} is not supported on Definitely Typed.`); | ||
} | ||
return version; | ||
}); | ||
} | ||
const typeScriptVersionLineParser = pm | ||
.regexp(/\/\/ (?:Minimum )?TypeScript Version: (\d.(\d))/, 1) | ||
.chain((v) => typescript_versions_1.TypeScriptVersion.all.includes(v) | ||
? pm.succeed(v) | ||
: pm.fail(`TypeScript ${v} is not yet supported.`)); | ||
const typeScriptVersionParser = pm | ||
.regexp(/\r?\n/) | ||
.then(typeScriptVersionLineParser) | ||
.fallback(typescript_versions_1.TypeScriptVersion.shipped[0]); | ||
function parseTypeScriptVersionLine(line) { | ||
const result = typeScriptVersionLineParser.parse(line); | ||
if (!result.status) { | ||
throw new Error(`Could not parse version: line is '${line}'`); | ||
exports.getTypesVersions = getTypesVersions; | ||
function checkPackageJsonOwners(packageName, packageJsonOwners) { | ||
const errors = []; | ||
for (const c of packageJsonOwners) { | ||
if (typeof c !== "object" || c === null) { | ||
errors.push(`${packageName}'s package.json has bad "owners": must be an array of type Array<{ name: string, url: string } | { name: string, githubUsername: string}>.`); | ||
continue; | ||
} | ||
if (!("name" in c) || typeof c.name !== "string") { | ||
errors.push(`${packageName}'s package.json has bad "name" in owner ${JSON.stringify(c)} | ||
Must be an object of type { name: string, url: string } | { name: string, githubUsername: string}.`); | ||
} | ||
else if (c.name === "My Self") { | ||
errors.push(`${packageName}'s package.json has bad "name" in owner ${JSON.stringify(c)} | ||
Author name should be your name, not the default.`); | ||
} | ||
if ("githubUsername" in c) { | ||
if (typeof c.githubUsername !== "string") { | ||
errors.push(`${packageName}'s package.json has bad "githubUsername" in owner ${JSON.stringify(c)} | ||
Must be an object of type { name: string, url: string } | { name: string, githubUsername: string}.`); | ||
} | ||
else if ("url" in c) { | ||
errors.push(`${packageName}'s package.json has bad owner: should not have both "githubUsername" and "url" properties in owner ${JSON.stringify(c)}`); | ||
} | ||
} | ||
else if ("url" in c && typeof c.url !== "string") { | ||
errors.push(`${packageName}'s package.json has bad "url" in owner ${JSON.stringify(c)} | ||
Must be an object of type { name: string, url: string } | { name: string, githubUsername: string}.`); | ||
} | ||
for (const key in c) { | ||
switch (key) { | ||
case "name": | ||
case "url": | ||
case "githubUsername": | ||
break; | ||
default: | ||
errors.push(`${packageName}'s package.json has bad owner: should not include property ${key} in ${JSON.stringify(c)}`); | ||
} | ||
} | ||
} | ||
return result.value; | ||
return errors; | ||
} | ||
exports.parseTypeScriptVersionLine = parseTypeScriptVersionLine; | ||
function reverse(s) { | ||
let out = ""; | ||
for (let i = s.length - 1; i >= 0; i--) { | ||
out += s[i]; | ||
const allLicenses = ["MIT" /* License.MIT */, "Apache-2.0" /* License.Apache20 */]; | ||
function getLicenseFromPackageJson(packageJsonLicense) { | ||
if (packageJsonLicense === undefined) { | ||
// tslint:disable-line strict-type-predicates (false positive) | ||
return "MIT" /* License.MIT */; | ||
} | ||
return out; | ||
if (typeof packageJsonLicense === "string" && packageJsonLicense === "MIT") { | ||
return [`Specifying '"license": "MIT"' is redundant, this is the default.`]; | ||
} | ||
if (allLicenses.includes(packageJsonLicense)) { | ||
return packageJsonLicense; | ||
} | ||
return [ | ||
`'package.json' license is ${JSON.stringify(packageJsonLicense)}.\nExpected one of: ${JSON.stringify(allLicenses)}}`, | ||
]; | ||
} | ||
function regexpIndexOf(s, rgx, start) { | ||
const index = s.slice(start).search(rgx); | ||
return index === -1 ? index : index + start; | ||
exports.getLicenseFromPackageJson = getLicenseFromPackageJson; | ||
// TODO: Move these checks into validatePackageJson and make it return an entire package.json type, not just Header | ||
// TODO: Expand these checks too, adding name and version just like dtslint | ||
function checkPackageJsonExportsAndAddPJsonEntry(exports, path) { | ||
if (exports === undefined) | ||
return exports; | ||
if (typeof exports === "string") { | ||
return exports; | ||
} | ||
if (typeof exports !== "object") { | ||
return [`Package exports at path ${path} should be an object or string.`]; | ||
} | ||
if (exports === null) { | ||
return [`Package exports at path ${path} should not be null.`]; | ||
} | ||
if (!exports["./package.json"]) { | ||
exports["./package.json"] = "./package.json"; | ||
} | ||
return exports; | ||
} | ||
function intOfString(str) { | ||
const n = Number.parseInt(str, 10); | ||
if (Number.isNaN(n)) { | ||
throw new Error(`Error in parseInt(${JSON.stringify(str)})`); | ||
exports.checkPackageJsonExportsAndAddPJsonEntry = checkPackageJsonExportsAndAddPJsonEntry; | ||
function checkPackageJsonImports(imports, path) { | ||
if (imports === undefined) | ||
return imports; | ||
if (typeof imports !== "object") { | ||
return [`Package imports at path ${path} should be an object or string.`]; | ||
} | ||
return n; | ||
else if (imports === null) { | ||
return [`Package imports at path ${path} should not be null.`]; | ||
} | ||
return imports; | ||
} | ||
exports.checkPackageJsonImports = checkPackageJsonImports; | ||
function checkPackageJsonType(type, path) { | ||
if (type === undefined) | ||
return type; | ||
if (type !== "module") { | ||
return [`Package type at path ${path} can only be 'module'.`]; | ||
} | ||
return type; | ||
} | ||
exports.checkPackageJsonType = checkPackageJsonType; | ||
/** | ||
* @param devDependencySelfName - pass the package name only for devDependencies | ||
*/ | ||
function checkPackageJsonDependencies(dependencies, path, allowedDependencies, devDependencySelfName) { | ||
if (dependencies === undefined) { | ||
return []; | ||
} | ||
if (dependencies === null || typeof dependencies !== "object") { | ||
return [`${path} should contain ${devDependencySelfName ? "devDependencies" : "dependencies"} or not exist.`]; | ||
} | ||
const errors = []; | ||
for (const dependencyName of Object.keys(dependencies)) { | ||
if (!dependencyName.startsWith("@types/") && !allowedDependencies.has(dependencyName)) { | ||
const msg = `Dependency ${dependencyName} not in the allowed dependencies list. | ||
Please make a pull request to microsoft/DefinitelyTyped-tools adding it to \`packages/definitions-parser/allowedPackageJsonDependencies.txt\`.`; | ||
errors.push(`In ${path}: ${msg}`); | ||
} | ||
const version = dependencies[dependencyName]; | ||
if (typeof version !== "string") { | ||
errors.push(`In ${path}: Dependency version for ${dependencyName} should be a string.`); | ||
} | ||
} | ||
if (devDependencySelfName) { | ||
const selfDependency = dependencies[devDependencySelfName]; | ||
if (selfDependency === undefined || selfDependency !== "workspace:.") { | ||
errors.push(`In ${path}: devDependencies must contain a self-reference to the current package like ${JSON.stringify(devDependencySelfName)}: "workspace:."`); | ||
} | ||
} | ||
return errors; | ||
} | ||
exports.checkPackageJsonDependencies = checkPackageJsonDependencies; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@definitelytyped/header-parser", | ||
"version": "0.0.178", | ||
"version": "0.0.179", | ||
"description": "", | ||
@@ -15,6 +15,2 @@ "author": "Nathan Shively-Sanders <nathansa@microsoft.com>", | ||
}, | ||
"scripts": { | ||
"build": "tsc -b", | ||
"test": "../../node_modules/.bin/jest --config ../../jest.config.js packages/header-parser" | ||
}, | ||
"bugs": { | ||
@@ -24,10 +20,16 @@ "url": "https://github.com/microsoft/DefinitelyTyped-tools/issues" | ||
"dependencies": { | ||
"@definitelytyped/typescript-versions": "^0.0.178", | ||
"@types/parsimmon": "^1.10.1", | ||
"parsimmon": "^1.13.0" | ||
"semver": "^7.3.7", | ||
"@definitelytyped/typescript-versions": "0.0.179", | ||
"@definitelytyped/utils": "0.0.179" | ||
}, | ||
"devDependencies": { | ||
"@types/semver": "^7.5.2" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"gitHead": "41ba894ba571e55fa91ef0bb0d44d6eb6d201943" | ||
} | ||
"scripts": { | ||
"build": "tsc -b", | ||
"test": "../../node_modules/.bin/jest --config ../../jest.config.js packages/header-parser" | ||
} | ||
} |
# DefinitelyTyped Header Parser | ||
This library parses headers of [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) types. | ||
This library parses package.jsons of [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) types. | ||
Its name is left over from when package information was stored in textual headers. | ||
# Contributing | ||
To build: `npm run build`. | ||
To test: `npm run test`. (Currently requires a re-build to test changes.) | ||
To build: `pnpm run build`. | ||
To test: `pnpm test`. | ||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
36389
7
487
12
1
1
1
+ Addedsemver@^7.3.7
+ Added@definitelytyped/typescript-versions@0.0.179(transitive)
+ Added@definitelytyped/utils@0.0.179(transitive)
+ Added@qiwi/npm-registry-client@8.9.1(transitive)
+ Added@types/node@14.18.63(transitive)
+ Addedajv@6.12.6(transitive)
+ Addedansi-regex@2.1.1(transitive)
+ Addedaproba@1.2.0(transitive)
+ Addedare-we-there-yet@1.1.7(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedassert-plus@1.0.0(transitive)
+ Addedasynckit@0.4.0(transitive)
+ Addedaws-sign2@0.7.0(transitive)
+ Addedaws4@1.13.0(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbase64-js@1.5.1(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedbl@4.1.0(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedbuffer@5.7.1(transitive)
+ Addedbuffer-from@1.1.2(transitive)
+ Addedbuiltins@1.0.3(transitive)
+ Addedcaseless@0.12.0(transitive)
+ Addedcharm@1.0.2(transitive)
+ Addedchownr@2.0.0(transitive)
+ Addedcode-point-at@1.1.0(transitive)
+ Addedcombined-stream@1.0.8(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedconcat-stream@2.0.0(transitive)
+ Addedconsole-control-strings@1.1.0(transitive)
+ Addedcore-util-is@1.0.21.0.3(transitive)
+ Addeddashdash@1.14.1(transitive)
+ Addeddelayed-stream@1.0.0(transitive)
+ Addeddelegates@1.0.0(transitive)
+ Addedecc-jsbn@0.1.2(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedextsprintf@1.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedforever-agent@0.6.1(transitive)
+ Addedform-data@2.3.3(transitive)
+ Addedfs-constants@1.0.0(transitive)
+ Addedfs-extra@8.1.0(transitive)
+ Addedfs-minipass@2.1.0(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfstream@1.0.12(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedgauge@2.7.4(transitive)
+ Addedgetpass@0.1.7(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhar-schema@2.0.0(transitive)
+ Addedhar-validator@5.1.5(transitive)
+ Addedhas-unicode@2.0.1(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedhosted-git-info@4.1.0(transitive)
+ Addedhttp-signature@1.2.0(transitive)
+ Addedieee754@1.2.1(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-core-module@2.14.0(transitive)
+ Addedis-fullwidth-code-point@1.0.0(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedjsbn@0.1.1(transitive)
+ Addedjson-schema@0.4.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson-stringify-safe@5.0.1(transitive)
+ Addedjsonfile@4.0.0(transitive)
+ Addedjsprim@1.4.2(transitive)
+ Addedlru-cache@6.0.0(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedminipass@3.3.65.0.0(transitive)
+ Addedminizlib@2.1.2(transitive)
+ Addedmkdirp@0.5.61.0.4(transitive)
+ Addednormalize-package-data@3.0.3(transitive)
+ Addednpm-package-arg@8.1.5(transitive)
+ Addednpmlog@4.1.2(transitive)
+ Addednumber-is-nan@1.0.1(transitive)
+ Addedoauth-sign@0.9.0(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedpsl@1.9.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedqs@6.5.3(transitive)
+ Addedreadable-stream@2.3.83.6.2(transitive)
+ Addedrequest@2.88.2(transitive)
+ Addedretry@0.12.0(transitive)
+ Addedrimraf@2.7.1(transitive)
+ Addedsafe-buffer@5.1.25.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsemver@7.6.2(transitive)
+ Addedset-blocking@2.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedslide@1.1.6(transitive)
+ Addedspdx-correct@3.2.0(transitive)
+ Addedspdx-exceptions@2.5.0(transitive)
+ Addedspdx-expression-parse@3.0.1(transitive)
+ Addedspdx-license-ids@3.0.18(transitive)
+ Addedsshpk@1.18.0(transitive)
+ Addedssri@8.0.1(transitive)
+ Addedstring-width@1.0.2(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedstrip-ansi@3.0.1(transitive)
+ Addedtar@6.2.1(transitive)
+ Addedtar-stream@2.2.0(transitive)
+ Addedtough-cookie@2.5.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addedtypedarray@0.0.6(transitive)
+ Addeduniversalify@0.1.2(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedvalidate-npm-package-license@3.0.4(transitive)
+ Addedvalidate-npm-package-name@3.0.0(transitive)
+ Addedverror@1.10.0(transitive)
+ Addedwide-align@1.1.5(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedyallist@4.0.0(transitive)
- Removed@types/parsimmon@^1.10.1
- Removedparsimmon@^1.13.0
- Removed@definitelytyped/typescript-versions@0.0.178(transitive)
- Removed@types/parsimmon@1.10.9(transitive)
- Removedparsimmon@1.18.1(transitive)