WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
|
||||
/**
|
||||
* This is the common logic for both the Node.js and web browser
|
||||
* implementations of `debug()`.
|
||||
*/
|
||||
|
||||
function setup(env) {
|
||||
createDebug.debug = createDebug;
|
||||
createDebug.default = createDebug;
|
||||
createDebug.coerce = coerce;
|
||||
createDebug.disable = disable;
|
||||
createDebug.enable = enable;
|
||||
createDebug.enabled = enabled;
|
||||
createDebug.humanize = require('ms');
|
||||
createDebug.destroy = destroy;
|
||||
|
||||
Object.keys(env).forEach(key => {
|
||||
createDebug[key] = env[key];
|
||||
});
|
||||
|
||||
/**
|
||||
* The currently active debug mode names, and names to skip.
|
||||
*/
|
||||
|
||||
createDebug.names = [];
|
||||
createDebug.skips = [];
|
||||
|
||||
/**
|
||||
* Map of special "%n" handling functions, for the debug "format" argument.
|
||||
*
|
||||
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
|
||||
*/
|
||||
createDebug.formatters = {};
|
||||
|
||||
/**
|
||||
* Selects a color for a debug namespace
|
||||
* @param {String} namespace The namespace string for the debug instance to be colored
|
||||
* @return {Number|String} An ANSI color code for the given namespace
|
||||
* @api private
|
||||
*/
|
||||
function selectColor(namespace) {
|
||||
let hash = 0;
|
||||
|
||||
for (let i = 0; i < namespace.length; i++) {
|
||||
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
||||
hash |= 0; // Convert to 32bit integer
|
||||
}
|
||||
|
||||
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
||||
}
|
||||
createDebug.selectColor = selectColor;
|
||||
|
||||
/**
|
||||
* Create a debugger with the given `namespace`.
|
||||
*
|
||||
* @param {String} namespace
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
function createDebug(namespace) {
|
||||
let prevTime;
|
||||
let enableOverride = null;
|
||||
let namespacesCache;
|
||||
let enabledCache;
|
||||
|
||||
function debug(...args) {
|
||||
// Disabled?
|
||||
if (!debug.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const self = debug;
|
||||
|
||||
// Set `diff` timestamp
|
||||
const curr = Number(new Date());
|
||||
const ms = curr - (prevTime || curr);
|
||||
self.diff = ms;
|
||||
self.prev = prevTime;
|
||||
self.curr = curr;
|
||||
prevTime = curr;
|
||||
|
||||
args[0] = createDebug.coerce(args[0]);
|
||||
|
||||
if (typeof args[0] !== 'string') {
|
||||
// Anything else let's inspect with %O
|
||||
args.unshift('%O');
|
||||
}
|
||||
|
||||
// Apply any `formatters` transformations
|
||||
let index = 0;
|
||||
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
||||
// If we encounter an escaped % then don't increase the array index
|
||||
if (match === '%%') {
|
||||
return '%';
|
||||
}
|
||||
index++;
|
||||
const formatter = createDebug.formatters[format];
|
||||
if (typeof formatter === 'function') {
|
||||
const val = args[index];
|
||||
match = formatter.call(self, val);
|
||||
|
||||
// Now we need to remove `args[index]` since it's inlined in the `format`
|
||||
args.splice(index, 1);
|
||||
index--;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
|
||||
// Apply env-specific formatting (colors, etc.)
|
||||
createDebug.formatArgs.call(self, args);
|
||||
|
||||
const logFn = self.log || createDebug.log;
|
||||
logFn.apply(self, args);
|
||||
}
|
||||
|
||||
debug.namespace = namespace;
|
||||
debug.useColors = createDebug.useColors();
|
||||
debug.color = createDebug.selectColor(namespace);
|
||||
debug.extend = extend;
|
||||
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
|
||||
|
||||
Object.defineProperty(debug, 'enabled', {
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
get: () => {
|
||||
if (enableOverride !== null) {
|
||||
return enableOverride;
|
||||
}
|
||||
if (namespacesCache !== createDebug.namespaces) {
|
||||
namespacesCache = createDebug.namespaces;
|
||||
enabledCache = createDebug.enabled(namespace);
|
||||
}
|
||||
|
||||
return enabledCache;
|
||||
},
|
||||
set: v => {
|
||||
enableOverride = v;
|
||||
}
|
||||
});
|
||||
|
||||
// Env-specific initialization logic for debug instances
|
||||
if (typeof createDebug.init === 'function') {
|
||||
createDebug.init(debug);
|
||||
}
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
||||
function extend(namespace, delimiter) {
|
||||
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
|
||||
newDebug.log = this.log;
|
||||
return newDebug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a debug mode by namespaces. This can include modes
|
||||
* separated by a colon and wildcards.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api public
|
||||
*/
|
||||
function enable(namespaces) {
|
||||
createDebug.save(namespaces);
|
||||
createDebug.namespaces = namespaces;
|
||||
|
||||
createDebug.names = [];
|
||||
createDebug.skips = [];
|
||||
|
||||
const split = (typeof namespaces === 'string' ? namespaces : '')
|
||||
.trim()
|
||||
.replace(/\s+/g, ',')
|
||||
.split(',')
|
||||
.filter(Boolean);
|
||||
|
||||
for (const ns of split) {
|
||||
if (ns[0] === '-') {
|
||||
createDebug.skips.push(ns.slice(1));
|
||||
} else {
|
||||
createDebug.names.push(ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given string matches a namespace template, honoring
|
||||
* asterisks as wildcards.
|
||||
*
|
||||
* @param {String} search
|
||||
* @param {String} template
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function matchesTemplate(search, template) {
|
||||
let searchIndex = 0;
|
||||
let templateIndex = 0;
|
||||
let starIndex = -1;
|
||||
let matchIndex = 0;
|
||||
|
||||
while (searchIndex < search.length) {
|
||||
if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {
|
||||
// Match character or proceed with wildcard
|
||||
if (template[templateIndex] === '*') {
|
||||
starIndex = templateIndex;
|
||||
matchIndex = searchIndex;
|
||||
templateIndex++; // Skip the '*'
|
||||
} else {
|
||||
searchIndex++;
|
||||
templateIndex++;
|
||||
}
|
||||
} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition
|
||||
// Backtrack to the last '*' and try to match more characters
|
||||
templateIndex = starIndex + 1;
|
||||
matchIndex++;
|
||||
searchIndex = matchIndex;
|
||||
} else {
|
||||
return false; // No match
|
||||
}
|
||||
}
|
||||
|
||||
// Handle trailing '*' in template
|
||||
while (templateIndex < template.length && template[templateIndex] === '*') {
|
||||
templateIndex++;
|
||||
}
|
||||
|
||||
return templateIndex === template.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable debug output.
|
||||
*
|
||||
* @return {String} namespaces
|
||||
* @api public
|
||||
*/
|
||||
function disable() {
|
||||
const namespaces = [
|
||||
...createDebug.names,
|
||||
...createDebug.skips.map(namespace => '-' + namespace)
|
||||
].join(',');
|
||||
createDebug.enable('');
|
||||
return namespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given mode name is enabled, false otherwise.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
function enabled(name) {
|
||||
for (const skip of createDebug.skips) {
|
||||
if (matchesTemplate(name, skip)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const ns of createDebug.names) {
|
||||
if (matchesTemplate(name, ns)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coerce `val`.
|
||||
*
|
||||
* @param {Mixed} val
|
||||
* @return {Mixed}
|
||||
* @api private
|
||||
*/
|
||||
function coerce(val) {
|
||||
if (val instanceof Error) {
|
||||
return val.stack || val.message;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX DO NOT USE. This is a temporary stub function.
|
||||
* XXX It WILL be removed in the next major release.
|
||||
*/
|
||||
function destroy() {
|
||||
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
||||
}
|
||||
|
||||
createDebug.enable(createDebug.load());
|
||||
|
||||
return createDebug;
|
||||
}
|
||||
|
||||
module.exports = setup;
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"name": "is-glob",
|
||||
"description": "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a better user experience.",
|
||||
"version": "4.0.3",
|
||||
"homepage": "https://github.com/micromatch/is-glob",
|
||||
"author": "Jon Schlinkert (https://github.com/jonschlinkert)",
|
||||
"contributors": [
|
||||
"Brian Woodward (https://twitter.com/doowb)",
|
||||
"Daniel Perez (https://tuvistavie.com)",
|
||||
"Jon Schlinkert (http://twitter.com/jonschlinkert)"
|
||||
],
|
||||
"repository": "micromatch/is-glob",
|
||||
"bugs": {
|
||||
"url": "https://github.com/micromatch/is-glob/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha && node benchmark.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp-format-md": "^0.1.10",
|
||||
"mocha": "^3.0.2"
|
||||
},
|
||||
"keywords": [
|
||||
"bash",
|
||||
"braces",
|
||||
"check",
|
||||
"exec",
|
||||
"expression",
|
||||
"extglob",
|
||||
"glob",
|
||||
"globbing",
|
||||
"globstar",
|
||||
"is",
|
||||
"match",
|
||||
"matches",
|
||||
"pattern",
|
||||
"regex",
|
||||
"regular",
|
||||
"string",
|
||||
"test"
|
||||
],
|
||||
"verb": {
|
||||
"layout": "default",
|
||||
"plugins": [
|
||||
"gulp-format-md"
|
||||
],
|
||||
"related": {
|
||||
"list": [
|
||||
"assemble",
|
||||
"base",
|
||||
"update",
|
||||
"verb"
|
||||
]
|
||||
},
|
||||
"reflinks": [
|
||||
"assemble",
|
||||
"bach",
|
||||
"base",
|
||||
"composer",
|
||||
"gulp",
|
||||
"has-glob",
|
||||
"is-valid-glob",
|
||||
"micromatch",
|
||||
"npm",
|
||||
"scaffold",
|
||||
"verb",
|
||||
"vinyl"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"for + if": {
|
||||
"name": "for + if",
|
||||
"browser": "Safari 10.0.1 (Mac OS X 10.12.1)",
|
||||
"suite": "itar-long",
|
||||
"hz": 24983.89047457792,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.014556136047743569,
|
||||
"rhz": 0.9435641971541613,
|
||||
"sampleSize": 206
|
||||
},
|
||||
"while + if": {
|
||||
"name": "while + if",
|
||||
"browser": "Safari 10.0.1 (Mac OS X 10.12.1)",
|
||||
"suite": "itar-long",
|
||||
"hz": 24686.899076943977,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.014123011962622743,
|
||||
"rhz": 0.9323477515027001,
|
||||
"sampleSize": 209
|
||||
},
|
||||
"array join": {
|
||||
"name": "array join",
|
||||
"browser": "Safari 10.0.1 (Mac OS X 10.12.1)",
|
||||
"suite": "itar-long",
|
||||
"hz": 26478.209484771287,
|
||||
"success": true,
|
||||
"fastest": true,
|
||||
"rme": 0.012780034002736902,
|
||||
"rhz": 1,
|
||||
"sampleSize": 209
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
var u=Object.defineProperty;var g=(s,n)=>u(s,"name",{value:n,configurable:!0});let t=!0;const l=typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{};let i=0;if(l.process&&l.process.env&&l.process.stdout){const{FORCE_COLOR:s,NODE_DISABLE_COLORS:n,NO_COLOR:r,TERM:o,COLORTERM:c}=l.process.env;n||r||s==="0"?t=!1:s==="1"||s==="2"||s==="3"?t=!0:o==="dumb"?t=!1:"CI"in l.process.env&&["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE","DRONE"].some(a=>a in l.process.env)?t=!0:t=process.stdout.isTTY,t&&(process.platform==="win32"||c&&(c==="truecolor"||c==="24bit")?i=3:o&&(o.endsWith("-256color")||o.endsWith("256"))?i=2:i=1)}let f={enabled:t,supportLevel:i};function e(s,n,r=1){const o=`\x1B[${s}m`,c=`\x1B[${n}m`,a=new RegExp(`\\x1b\\[${n}m`,"g");return p=>f.enabled&&f.supportLevel>=r?o+(""+p).replace(a,o)+c:""+p}g(e,"kolorist");const b=e(30,39),d=e(33,39),O=e(90,39),C=e(92,39),R=e(95,39),I=e(96,39),L=e(44,49),E=e(100,49),T=e(103,49);export{b as a,T as b,L as c,E as d,R as e,C as f,O as g,I as l,f as o,d as y};
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2024_string = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2024_string = {
|
||||
libs: [],
|
||||
variables: [['String', base_config_1.TYPE]],
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
|
||||
// @ts-ignore `esbuild` may not be installed
|
||||
import type esbuild from 'esbuild'
|
||||
|
||||
/* eslint-enable @typescript-eslint/ban-ts-comment */
|
||||
|
||||
export type EsbuildTarget = string | string[]
|
||||
|
||||
export type EsbuildLoader = esbuild.Loader
|
||||
export type EsbuildTransformOptions = esbuild.TransformOptions
|
||||
export type EsbuildTransformResult = esbuild.TransformResult
|
||||
|
||||
export type EsbuildMessage = esbuild.Message
|
||||
|
||||
export type DepsOptimizerEsbuildOptions = Omit<
|
||||
esbuild.BuildOptions,
|
||||
| 'bundle'
|
||||
| 'entryPoints'
|
||||
| 'external'
|
||||
| 'write'
|
||||
| 'watch'
|
||||
| 'outdir'
|
||||
| 'outfile'
|
||||
| 'outbase'
|
||||
| 'outExtension'
|
||||
| 'metafile'
|
||||
>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,959 @@
|
||||
// Copied from `@types/prettier`
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5bb07fc4b087cb7ee91084afa6fe750551a7bbb1/types/prettier/index.d.ts
|
||||
|
||||
// Minimum TypeScript Version: 4.2
|
||||
|
||||
// Add `export {}` here to shut off automatic exporting from index.d.ts. There
|
||||
// are quite a few utility types here that don't need to be shipped with the
|
||||
// exported module.
|
||||
export {};
|
||||
|
||||
import { builders, printer, utils } from "./doc.js";
|
||||
|
||||
export namespace doc {
|
||||
export { builders, printer, utils };
|
||||
}
|
||||
|
||||
// This utility is here to handle the case where you have an explicit union
|
||||
// between string literals and the generic string type. It would normally
|
||||
// resolve out to just the string type, but this generic LiteralUnion maintains
|
||||
// the intellisense of the original union.
|
||||
//
|
||||
// It comes from this issue: microsoft/TypeScript#29729:
|
||||
// https://github.com/microsoft/TypeScript/issues/29729#issuecomment-700527227
|
||||
export type LiteralUnion<T extends U, U = string> =
|
||||
T | (Pick<U, never> & { _?: never | undefined });
|
||||
|
||||
export type AST = any;
|
||||
export type Doc = doc.builders.Doc;
|
||||
|
||||
// The type of elements that make up the given array T.
|
||||
type ArrayElement<T> = T extends Array<infer E> ? E : never;
|
||||
|
||||
// A union of the properties of the given object that are arrays.
|
||||
type ArrayProperties<T> = {
|
||||
[K in keyof T]: NonNullable<T[K]> extends readonly any[] ? K : never;
|
||||
}[keyof T];
|
||||
|
||||
// A union of the properties of the given array T that can be used to index it.
|
||||
// If the array is a tuple, then that's going to be the explicit indices of the
|
||||
// array, otherwise it's going to just be number.
|
||||
type IndexProperties<T extends { length: number }> =
|
||||
IsTuple<T> extends true ? Exclude<Partial<T>["length"], T["length"]> : number;
|
||||
|
||||
// Effectively performing T[P], except that it's telling TypeScript that it's
|
||||
// safe to do this for tuples, arrays, or objects.
|
||||
type IndexValue<T, P> = T extends any[]
|
||||
? P extends number
|
||||
? T[P]
|
||||
: never
|
||||
: P extends keyof T
|
||||
? T[P]
|
||||
: never;
|
||||
|
||||
// Determines if an object T is an array like string[] (in which case this
|
||||
// evaluates to false) or a tuple like [string] (in which case this evaluates to
|
||||
// true).
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type IsTuple<T> = T extends []
|
||||
? true
|
||||
: T extends [infer First, ...infer Remain]
|
||||
? IsTuple<Remain>
|
||||
: false;
|
||||
|
||||
type CallProperties<T> = T extends any[] ? IndexProperties<T> : keyof T;
|
||||
type IterProperties<T> = T extends any[]
|
||||
? IndexProperties<T>
|
||||
: ArrayProperties<T>;
|
||||
|
||||
type CallCallback<T, U> = (path: AstPath<T>, index: number, value: any) => U;
|
||||
type EachCallback<T> = (
|
||||
path: AstPath<ArrayElement<T>>,
|
||||
index: number,
|
||||
value: any,
|
||||
) => void;
|
||||
type MapCallback<T, U> = (
|
||||
path: AstPath<ArrayElement<T>>,
|
||||
index: number,
|
||||
value: any,
|
||||
) => U;
|
||||
|
||||
// https://github.com/prettier/prettier/blob/next/src/common/ast-path.js
|
||||
export class AstPath<T = any> {
|
||||
constructor(value: T);
|
||||
|
||||
get key(): string | null;
|
||||
get index(): number | null;
|
||||
get node(): T;
|
||||
get parent(): T | null;
|
||||
get grandparent(): T | null;
|
||||
get isInArray(): boolean;
|
||||
get siblings(): T[] | null;
|
||||
get next(): T | null;
|
||||
get previous(): T | null;
|
||||
get isFirst(): boolean;
|
||||
get isLast(): boolean;
|
||||
get isRoot(): boolean;
|
||||
get root(): T;
|
||||
get ancestors(): T[];
|
||||
|
||||
stack: T[];
|
||||
|
||||
callParent<U>(callback: (path: this) => U, count?: number): U;
|
||||
|
||||
/**
|
||||
* @deprecated Please use `AstPath#key` or `AstPath#index`
|
||||
*/
|
||||
getName(): PropertyKey | null;
|
||||
|
||||
/**
|
||||
* @deprecated Please use `AstPath#node` or `AstPath#siblings`
|
||||
*/
|
||||
getValue(): T;
|
||||
|
||||
getNode(count?: number): T | null;
|
||||
|
||||
getParentNode(count?: number): T | null;
|
||||
|
||||
match(
|
||||
...predicates: Array<
|
||||
(node: any, name: string | null, number: number | null) => boolean
|
||||
>
|
||||
): boolean;
|
||||
|
||||
// For each of the tree walk functions (call, each, and map) this provides 5
|
||||
// strict type signatures, along with a fallback at the end if you end up
|
||||
// calling more than 5 properties deep. This helps a lot with typing because
|
||||
// for the majority of cases you're calling fewer than 5 properties, so the
|
||||
// tree walk functions have a clearer understanding of what you're doing.
|
||||
//
|
||||
// Note that resolving these types is somewhat complicated, and it wasn't
|
||||
// even supported until TypeScript 4.2 (before it would just say that the
|
||||
// type instantiation was excessively deep and possibly infinite).
|
||||
|
||||
call<U>(callback: CallCallback<T, U>): U;
|
||||
call<U, P1 extends CallProperties<T>>(
|
||||
callback: CallCallback<IndexValue<T, P1>, U>,
|
||||
prop1: P1,
|
||||
): U;
|
||||
call<U, P1 extends keyof T, P2 extends CallProperties<T[P1]>>(
|
||||
callback: CallCallback<IndexValue<IndexValue<T, P1>, P2>, U>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
): U;
|
||||
call<
|
||||
U,
|
||||
P1 extends keyof T,
|
||||
P2 extends CallProperties<T[P1]>,
|
||||
P3 extends CallProperties<IndexValue<T[P1], P2>>,
|
||||
>(
|
||||
callback: CallCallback<
|
||||
IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>,
|
||||
U
|
||||
>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
): U;
|
||||
call<
|
||||
U,
|
||||
P1 extends keyof T,
|
||||
P2 extends CallProperties<T[P1]>,
|
||||
P3 extends CallProperties<IndexValue<T[P1], P2>>,
|
||||
P4 extends CallProperties<IndexValue<IndexValue<T[P1], P2>, P3>>,
|
||||
>(
|
||||
callback: CallCallback<
|
||||
IndexValue<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>, P4>,
|
||||
U
|
||||
>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
prop4: P4,
|
||||
): U;
|
||||
call<U, P extends PropertyKey>(
|
||||
callback: CallCallback<any, U>,
|
||||
prop1: P,
|
||||
prop2: P,
|
||||
prop3: P,
|
||||
prop4: P,
|
||||
...props: P[]
|
||||
): U;
|
||||
|
||||
each(callback: EachCallback<T>): void;
|
||||
each<P1 extends IterProperties<T>>(
|
||||
callback: EachCallback<IndexValue<T, P1>>,
|
||||
prop1: P1,
|
||||
): void;
|
||||
each<P1 extends keyof T, P2 extends IterProperties<T[P1]>>(
|
||||
callback: EachCallback<IndexValue<IndexValue<T, P1>, P2>>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
): void;
|
||||
each<
|
||||
P1 extends keyof T,
|
||||
P2 extends IterProperties<T[P1]>,
|
||||
P3 extends IterProperties<IndexValue<T[P1], P2>>,
|
||||
>(
|
||||
callback: EachCallback<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
): void;
|
||||
each<
|
||||
P1 extends keyof T,
|
||||
P2 extends IterProperties<T[P1]>,
|
||||
P3 extends IterProperties<IndexValue<T[P1], P2>>,
|
||||
P4 extends IterProperties<IndexValue<IndexValue<T[P1], P2>, P3>>,
|
||||
>(
|
||||
callback: EachCallback<
|
||||
IndexValue<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>, P4>
|
||||
>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
prop4: P4,
|
||||
): void;
|
||||
each(
|
||||
callback: EachCallback<any[]>,
|
||||
prop1: PropertyKey,
|
||||
prop2: PropertyKey,
|
||||
prop3: PropertyKey,
|
||||
prop4: PropertyKey,
|
||||
...props: PropertyKey[]
|
||||
): void;
|
||||
|
||||
map<U>(callback: MapCallback<T, U>): U[];
|
||||
map<U, P1 extends IterProperties<T>>(
|
||||
callback: MapCallback<IndexValue<T, P1>, U>,
|
||||
prop1: P1,
|
||||
): U[];
|
||||
map<U, P1 extends keyof T, P2 extends IterProperties<T[P1]>>(
|
||||
callback: MapCallback<IndexValue<IndexValue<T, P1>, P2>, U>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
): U[];
|
||||
map<
|
||||
U,
|
||||
P1 extends keyof T,
|
||||
P2 extends IterProperties<T[P1]>,
|
||||
P3 extends IterProperties<IndexValue<T[P1], P2>>,
|
||||
>(
|
||||
callback: MapCallback<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>, U>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
): U[];
|
||||
map<
|
||||
U,
|
||||
P1 extends keyof T,
|
||||
P2 extends IterProperties<T[P1]>,
|
||||
P3 extends IterProperties<IndexValue<T[P1], P2>>,
|
||||
P4 extends IterProperties<IndexValue<IndexValue<T[P1], P2>, P3>>,
|
||||
>(
|
||||
callback: MapCallback<
|
||||
IndexValue<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>, P4>,
|
||||
U
|
||||
>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
prop4: P4,
|
||||
): U[];
|
||||
map<U>(
|
||||
callback: MapCallback<any[], U>,
|
||||
prop1: PropertyKey,
|
||||
prop2: PropertyKey,
|
||||
prop3: PropertyKey,
|
||||
prop4: PropertyKey,
|
||||
...props: PropertyKey[]
|
||||
): U[];
|
||||
}
|
||||
|
||||
/** @deprecated `FastPath` was renamed to `AstPath` */
|
||||
export type FastPath<T = any> = AstPath<T>;
|
||||
|
||||
export type BuiltInParser = (text: string, options?: any) => AST;
|
||||
export type BuiltInParserName =
|
||||
| "acorn"
|
||||
| "angular"
|
||||
| "babel-flow"
|
||||
| "babel-ts"
|
||||
| "babel"
|
||||
| "css"
|
||||
| "espree"
|
||||
| "flow"
|
||||
| "glimmer"
|
||||
| "graphql"
|
||||
| "html"
|
||||
| "json-stringify"
|
||||
| "json"
|
||||
| "json5"
|
||||
| "jsonc"
|
||||
| "less"
|
||||
| "lwc"
|
||||
| "markdown"
|
||||
| "mdx"
|
||||
| "meriyah"
|
||||
| "mjml"
|
||||
| "scss"
|
||||
| "typescript"
|
||||
| "vue"
|
||||
| "yaml";
|
||||
export type BuiltInParsers = Record<BuiltInParserName, BuiltInParser>;
|
||||
|
||||
/**
|
||||
* For use in `.prettierrc.js`, `.prettierrc.ts`, `.prettierrc.cjs`, `.prettierrc.cts`, `prettierrc.mjs`, `prettierrc.mts`, `prettier.config.js`, `prettier.config.ts`, `prettier.config.cjs`, `prettier.config.cts`, `prettier.config.mjs`, `prettier.config.mts`
|
||||
*/
|
||||
export interface Config extends Options {
|
||||
overrides?: Array<{
|
||||
files: string | string[];
|
||||
excludeFiles?: string | string[];
|
||||
options?: Options;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface Options extends Partial<RequiredOptions> {}
|
||||
|
||||
export interface RequiredOptions extends doc.printer.Options {
|
||||
/**
|
||||
* Print semicolons at the ends of statements.
|
||||
* @default true
|
||||
*/
|
||||
semi: boolean;
|
||||
/**
|
||||
* Use single quotes instead of double quotes.
|
||||
* @default false
|
||||
*/
|
||||
singleQuote: boolean;
|
||||
/**
|
||||
* Use single quotes in JSX.
|
||||
* @default false
|
||||
*/
|
||||
jsxSingleQuote: boolean;
|
||||
/**
|
||||
* Print trailing commas wherever possible.
|
||||
* @default "all"
|
||||
*/
|
||||
trailingComma: "none" | "es5" | "all";
|
||||
/**
|
||||
* Print spaces between brackets in object literals.
|
||||
* @default true
|
||||
*/
|
||||
bracketSpacing: boolean;
|
||||
/**
|
||||
* How to wrap object literals.
|
||||
* @default "preserve"
|
||||
*/
|
||||
objectWrap: "preserve" | "collapse";
|
||||
/**
|
||||
* Put the `>` of a multi-line HTML (HTML, JSX, Vue, Angular) element at the end of the last line instead of being
|
||||
* alone on the next line (does not apply to self closing elements).
|
||||
* @default false
|
||||
*/
|
||||
bracketSameLine: boolean;
|
||||
/**
|
||||
* Format only a segment of a file.
|
||||
* @default 0
|
||||
*/
|
||||
rangeStart: number;
|
||||
/**
|
||||
* Format only a segment of a file.
|
||||
* @default Number.POSITIVE_INFINITY
|
||||
*/
|
||||
rangeEnd: number;
|
||||
/**
|
||||
* Specify which parser to use.
|
||||
*/
|
||||
parser: LiteralUnion<BuiltInParserName>;
|
||||
/**
|
||||
* Specify the input filepath. This will be used to do parser inference.
|
||||
*/
|
||||
filepath: string;
|
||||
/**
|
||||
* Prettier can restrict itself to only format files that contain a special comment, called a pragma, at the top of the file.
|
||||
* This is very useful when gradually transitioning large, unformatted codebases to prettier.
|
||||
* @default false
|
||||
*/
|
||||
requirePragma: boolean;
|
||||
/**
|
||||
* Prettier can insert a special @format marker at the top of files specifying that
|
||||
* the file has been formatted with prettier. This works well when used in tandem with
|
||||
* the --require-pragma option. If there is already a docblock at the top of
|
||||
* the file then this option will add a newline to it with the @format marker.
|
||||
* @default false
|
||||
*/
|
||||
insertPragma: boolean;
|
||||
/**
|
||||
* Prettier can allow individual files to opt out of formatting if they contain a special comment, called a pragma, at the top of the file.
|
||||
* @default false
|
||||
*/
|
||||
checkIgnorePragma: boolean;
|
||||
/**
|
||||
* By default, Prettier will wrap markdown text as-is since some services use a linebreak-sensitive renderer.
|
||||
* In some cases you may want to rely on editor/viewer soft wrapping instead, so this option allows you to opt out.
|
||||
* @default "preserve"
|
||||
*/
|
||||
proseWrap: "always" | "never" | "preserve";
|
||||
/**
|
||||
* Include parentheses around a sole arrow function parameter.
|
||||
* @default "always"
|
||||
*/
|
||||
arrowParens: "avoid" | "always";
|
||||
/**
|
||||
* Provide ability to support new languages to prettier.
|
||||
*/
|
||||
plugins: Array<string | URL | Plugin>;
|
||||
/**
|
||||
* How to handle whitespaces in HTML.
|
||||
* @default "css"
|
||||
*/
|
||||
htmlWhitespaceSensitivity: "css" | "strict" | "ignore";
|
||||
/**
|
||||
* Which end of line characters to apply.
|
||||
* @default "lf"
|
||||
*/
|
||||
endOfLine: "auto" | "lf" | "crlf" | "cr";
|
||||
/**
|
||||
* Change when properties in objects are quoted.
|
||||
* @default "as-needed"
|
||||
*/
|
||||
quoteProps: "as-needed" | "consistent" | "preserve";
|
||||
/**
|
||||
* Whether or not to indent the code inside <script> and <style> tags in Vue files.
|
||||
* @default false
|
||||
*/
|
||||
vueIndentScriptAndStyle: boolean;
|
||||
/**
|
||||
* Control whether Prettier formats quoted code embedded in the file.
|
||||
* @default "auto"
|
||||
*/
|
||||
embeddedLanguageFormatting: "auto" | "off";
|
||||
/**
|
||||
* Enforce single attribute per line in HTML, Vue and JSX.
|
||||
* @default false
|
||||
*/
|
||||
singleAttributePerLine: boolean;
|
||||
/**
|
||||
* Where to print operators when binary expressions wrap lines.
|
||||
* @default "end"
|
||||
*/
|
||||
experimentalOperatorPosition: "start" | "end";
|
||||
/**
|
||||
* Use curious ternaries, with the question mark after the condition, instead
|
||||
* of on the same line as the consequent.
|
||||
* @default false
|
||||
*/
|
||||
experimentalTernaries: boolean;
|
||||
/**
|
||||
* Put the `>` of a multi-line JSX element at the end of the last line instead of being alone on the next line.
|
||||
* @default false
|
||||
* @deprecated use bracketSameLine instead
|
||||
*/
|
||||
jsxBracketSameLine?: boolean;
|
||||
/**
|
||||
* Arbitrary additional values on an options object are always allowed.
|
||||
*/
|
||||
[_: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ParserOptions<T = any> extends RequiredOptions {
|
||||
locStart: (node: T) => number;
|
||||
locEnd: (node: T) => number;
|
||||
originalText: string;
|
||||
}
|
||||
|
||||
export interface Plugin<T = any> {
|
||||
languages?: SupportLanguage[] | undefined;
|
||||
parsers?: { [parserName: string]: Parser<T> } | undefined;
|
||||
printers?: { [astFormat: string]: Printer<T> } | undefined;
|
||||
options?: SupportOptions | undefined;
|
||||
defaultOptions?: Partial<RequiredOptions> | undefined;
|
||||
}
|
||||
|
||||
export interface Parser<T = any> {
|
||||
parse: (text: string, options: ParserOptions<T>) => T | Promise<T>;
|
||||
astFormat: string;
|
||||
hasPragma?: ((text: string) => boolean) | undefined;
|
||||
hasIgnorePragma?: ((text: string) => boolean) | undefined;
|
||||
locStart: (node: T) => number;
|
||||
locEnd: (node: T) => number;
|
||||
preprocess?:
|
||||
| ((text: string, options: ParserOptions<T>) => string | Promise<string>)
|
||||
| undefined;
|
||||
}
|
||||
|
||||
export interface Printer<T = any> {
|
||||
print(
|
||||
path: AstPath<T>,
|
||||
options: ParserOptions<T>,
|
||||
print: (
|
||||
selector?: string | number | Array<string | number> | AstPath<T>,
|
||||
args?: unknown,
|
||||
) => Doc,
|
||||
args?: unknown,
|
||||
): Doc;
|
||||
printPrettierIgnored?(
|
||||
path: AstPath<T>,
|
||||
options: ParserOptions<T>,
|
||||
print: (
|
||||
selector?: string | number | Array<string | number> | AstPath<T>,
|
||||
args?: unknown,
|
||||
) => Doc,
|
||||
args?: unknown,
|
||||
): Doc;
|
||||
embed?:
|
||||
| ((
|
||||
path: AstPath,
|
||||
options: Options,
|
||||
) =>
|
||||
| ((
|
||||
textToDoc: (text: string, options: Options) => Promise<Doc>,
|
||||
print: (
|
||||
selector?: string | number | Array<string | number> | AstPath,
|
||||
args?: unknown,
|
||||
) => Doc,
|
||||
path: AstPath,
|
||||
options: Options,
|
||||
) => Promise<Doc | undefined> | Doc | undefined)
|
||||
| Doc
|
||||
| null)
|
||||
| undefined;
|
||||
preprocess?:
|
||||
((ast: T, options: ParserOptions<T>) => T | Promise<T>) | undefined;
|
||||
insertPragma?: (text: string) => string;
|
||||
/**
|
||||
* @returns `null` if you want to remove this node
|
||||
* @returns `void` if you want to use modified `cloned`
|
||||
* @returns anything if you want to replace the node with it
|
||||
*/
|
||||
massageAstNode?:
|
||||
((original: any, cloned: any, parent: any) => any) | undefined;
|
||||
hasPrettierIgnore?: ((path: AstPath<T>) => boolean) | undefined;
|
||||
canAttachComment?: ((node: T, ancestors: T[]) => boolean) | undefined;
|
||||
isBlockComment?: ((node: T) => boolean) | undefined;
|
||||
willPrintOwnComments?: ((path: AstPath<T>) => boolean) | undefined;
|
||||
printComment?:
|
||||
((commentPath: AstPath<T>, options: ParserOptions<T>) => Doc) | undefined;
|
||||
/**
|
||||
* By default, Prettier searches all object properties (except for a few predefined ones) of each node recursively.
|
||||
* This function can be provided to override that behavior.
|
||||
* @param node The node whose children should be returned.
|
||||
* @param options Current options.
|
||||
* @returns `[]` if the node has no children or `undefined` to fall back on the default behavior.
|
||||
*/
|
||||
getCommentChildNodes?:
|
||||
((node: T, options: ParserOptions<T>) => T[] | undefined) | undefined;
|
||||
handleComments?:
|
||||
| {
|
||||
ownLine?:
|
||||
| ((
|
||||
commentNode: any,
|
||||
text: string,
|
||||
options: ParserOptions<T>,
|
||||
ast: T,
|
||||
isLastComment: boolean,
|
||||
) => boolean)
|
||||
| undefined;
|
||||
endOfLine?:
|
||||
| ((
|
||||
commentNode: any,
|
||||
text: string,
|
||||
options: ParserOptions<T>,
|
||||
ast: T,
|
||||
isLastComment: boolean,
|
||||
) => boolean)
|
||||
| undefined;
|
||||
remaining?:
|
||||
| ((
|
||||
commentNode: any,
|
||||
text: string,
|
||||
options: ParserOptions<T>,
|
||||
ast: T,
|
||||
isLastComment: boolean,
|
||||
) => boolean)
|
||||
| undefined;
|
||||
}
|
||||
| undefined;
|
||||
getVisitorKeys?:
|
||||
((node: T, nonTraversableKeys: Set<string>) => string[]) | undefined;
|
||||
}
|
||||
|
||||
export interface CursorOptions extends Options {
|
||||
/**
|
||||
* Specify where the cursor is.
|
||||
*/
|
||||
cursorOffset: number;
|
||||
}
|
||||
|
||||
export interface CursorResult {
|
||||
formatted: string;
|
||||
cursorOffset: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* `format` is used to format text using Prettier. [Options](https://prettier.io/docs/options) may be provided to override the defaults.
|
||||
*/
|
||||
export function format(source: string, options?: Options): Promise<string>;
|
||||
|
||||
/**
|
||||
* `check` checks to see if the file has been formatted with Prettier given those options and returns a `Boolean`.
|
||||
* This is similar to the `--list-different` parameter in the CLI and is useful for running Prettier in CI scenarios.
|
||||
*/
|
||||
export function check(source: string, options?: Options): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* `formatWithCursor` both formats the code, and translates a cursor position from unformatted code to formatted code.
|
||||
* This is useful for editor integrations, to prevent the cursor from moving when code is formatted.
|
||||
*
|
||||
* The `cursorOffset` option should be provided, to specify where the cursor is.
|
||||
*/
|
||||
export function formatWithCursor(
|
||||
source: string,
|
||||
options: CursorOptions,
|
||||
): Promise<CursorResult>;
|
||||
|
||||
export interface ResolveConfigOptions {
|
||||
/**
|
||||
* If set to `false`, all caching will be bypassed.
|
||||
*/
|
||||
useCache?: boolean | undefined;
|
||||
/**
|
||||
* Pass directly the path of the config file if you don't wish to search for it.
|
||||
*/
|
||||
config?: string | URL | undefined;
|
||||
/**
|
||||
* If set to `true` and an `.editorconfig` file is in your project,
|
||||
* Prettier will parse it and convert its properties to the corresponding prettier configuration.
|
||||
* This configuration will be overridden by `.prettierrc`, etc. Currently,
|
||||
* the following EditorConfig properties are supported:
|
||||
* - indent_style
|
||||
* - indent_size/tab_width
|
||||
* - max_line_length
|
||||
*/
|
||||
editorconfig?: boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* `resolveConfig` can be used to resolve configuration for a given source file,
|
||||
* passing its path or url as the first argument. The config search will start at
|
||||
* the directory of the file location and continue to search up the directory.
|
||||
*
|
||||
* A promise is returned which will resolve to:
|
||||
*
|
||||
* - An options object, providing a [config file](https://prettier.io/docs/configuration) was found.
|
||||
* - `null`, if no file was found.
|
||||
*
|
||||
* The promise will be rejected if there was an error parsing the configuration file.
|
||||
*/
|
||||
export function resolveConfig(
|
||||
fileUrlOrPath: string | URL,
|
||||
options?: ResolveConfigOptions,
|
||||
): Promise<Options | null>;
|
||||
|
||||
/**
|
||||
* `resolveConfigFile` can be used to find the path of the Prettier configuration file,
|
||||
* that will be used when resolving the config (i.e. when calling `resolveConfig`).
|
||||
*
|
||||
* A promise is returned which will resolve to:
|
||||
*
|
||||
* - The path of the configuration file.
|
||||
* - `null`, if no file was found.
|
||||
*
|
||||
* The promise will be rejected if there was an error parsing the configuration file.
|
||||
*/
|
||||
export function resolveConfigFile(
|
||||
fileUrlOrPath?: string | URL,
|
||||
): Promise<string | null>;
|
||||
|
||||
/**
|
||||
* As you repeatedly call `resolveConfig`, the file system structure will be cached for performance. This function will clear the cache.
|
||||
* Generally this is only needed for editor integrations that know that the file system has changed since the last format took place.
|
||||
*/
|
||||
export function clearConfigCache(): Promise<void>;
|
||||
|
||||
export interface SupportLanguage {
|
||||
name: string;
|
||||
parsers: BuiltInParserName[] | string[];
|
||||
group?: string | undefined;
|
||||
tmScope?: string | undefined;
|
||||
aceMode?: string | undefined;
|
||||
codemirrorMode?: string | undefined;
|
||||
codemirrorMimeType?: string | undefined;
|
||||
aliases?: string[] | undefined;
|
||||
extensions?: string[] | undefined;
|
||||
filenames?: string[] | undefined;
|
||||
linguistLanguageId?: number | undefined;
|
||||
vscodeLanguageIds?: string[] | undefined;
|
||||
interpreters?: string[] | undefined;
|
||||
isSupported?: ((options: { filepath: string }) => boolean) | undefined;
|
||||
}
|
||||
|
||||
export interface SupportOptionRange {
|
||||
start: number;
|
||||
end: number;
|
||||
step: number;
|
||||
}
|
||||
|
||||
export type SupportOptionType =
|
||||
"int" | "string" | "boolean" | "choice" | "path";
|
||||
|
||||
export type CoreCategoryType =
|
||||
"Config" | "Editor" | "Format" | "Other" | "Output" | "Global" | "Special";
|
||||
|
||||
export interface BaseSupportOption<Type extends SupportOptionType> {
|
||||
readonly name?: string | undefined;
|
||||
/**
|
||||
* Usually you can use {@link CoreCategoryType}
|
||||
*/
|
||||
category: string;
|
||||
/**
|
||||
* The type of the option.
|
||||
*
|
||||
* When passing a type other than the ones listed below, the option is
|
||||
* treated as taking any string as argument, and `--option <${type}>` will
|
||||
* be displayed in --help.
|
||||
*/
|
||||
type: Type;
|
||||
/**
|
||||
* Indicate that the option is deprecated.
|
||||
*
|
||||
* Use a string to add an extra message to --help for the option,
|
||||
* for example to suggest a replacement option.
|
||||
*/
|
||||
deprecated?: true | string | undefined;
|
||||
/**
|
||||
* Description to be displayed in --help. If omitted, the option won't be
|
||||
* shown at all in --help.
|
||||
*/
|
||||
description?: string | undefined;
|
||||
}
|
||||
|
||||
export interface IntSupportOption extends BaseSupportOption<"int"> {
|
||||
default?: number | undefined;
|
||||
array?: false | undefined;
|
||||
range?: SupportOptionRange | undefined;
|
||||
}
|
||||
|
||||
export interface IntArraySupportOption extends BaseSupportOption<"int"> {
|
||||
default?: Array<{ value: number[] }> | undefined;
|
||||
array: true;
|
||||
}
|
||||
|
||||
export interface StringSupportOption extends BaseSupportOption<"string"> {
|
||||
default?: string | undefined;
|
||||
array?: false | undefined;
|
||||
}
|
||||
|
||||
export interface StringArraySupportOption extends BaseSupportOption<"string"> {
|
||||
default?: Array<{ value: string[] }> | undefined;
|
||||
array: true;
|
||||
}
|
||||
|
||||
export interface BooleanSupportOption extends BaseSupportOption<"boolean"> {
|
||||
default?: boolean | undefined;
|
||||
array?: false | undefined;
|
||||
description: string;
|
||||
oppositeDescription?: string | undefined;
|
||||
}
|
||||
|
||||
export interface BooleanArraySupportOption extends BaseSupportOption<"boolean"> {
|
||||
default?: Array<{ value: boolean[] }> | undefined;
|
||||
array: true;
|
||||
}
|
||||
|
||||
export interface ChoiceSupportOption<
|
||||
Value = any,
|
||||
> extends BaseSupportOption<"choice"> {
|
||||
default?: Value | Array<{ value: Value }> | undefined;
|
||||
description: string;
|
||||
choices: Array<{
|
||||
value: Value;
|
||||
description: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface PathSupportOption extends BaseSupportOption<"path"> {
|
||||
default?: string | undefined;
|
||||
array?: false | undefined;
|
||||
}
|
||||
|
||||
export interface PathArraySupportOption extends BaseSupportOption<"path"> {
|
||||
default?: Array<{ value: string[] }> | undefined;
|
||||
array: true;
|
||||
}
|
||||
|
||||
export type SupportOption =
|
||||
| IntSupportOption
|
||||
| IntArraySupportOption
|
||||
| StringSupportOption
|
||||
| StringArraySupportOption
|
||||
| BooleanSupportOption
|
||||
| BooleanArraySupportOption
|
||||
| ChoiceSupportOption
|
||||
| PathSupportOption
|
||||
| PathArraySupportOption;
|
||||
|
||||
export interface SupportOptions extends Record<string, SupportOption> {}
|
||||
|
||||
export interface SupportInfo {
|
||||
languages: SupportLanguage[];
|
||||
options: SupportOption[];
|
||||
}
|
||||
|
||||
export interface FileInfoOptions {
|
||||
ignorePath?: string | URL | (string | URL)[] | undefined;
|
||||
withNodeModules?: boolean | undefined;
|
||||
plugins?: Array<string | URL | Plugin> | undefined;
|
||||
resolveConfig?: boolean | undefined;
|
||||
}
|
||||
|
||||
export interface FileInfoResult {
|
||||
ignored: boolean;
|
||||
inferredParser: string | null;
|
||||
}
|
||||
|
||||
export function getFileInfo(
|
||||
file: string | URL,
|
||||
options?: FileInfoOptions,
|
||||
): Promise<FileInfoResult>;
|
||||
|
||||
export interface SupportInfoOptions {
|
||||
plugins?: Array<string | URL | Plugin> | undefined;
|
||||
showDeprecated?: boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object representing the parsers, languages and file types Prettier supports for the current version.
|
||||
*/
|
||||
export function getSupportInfo(
|
||||
options?: SupportInfoOptions,
|
||||
): Promise<SupportInfo>;
|
||||
|
||||
/**
|
||||
* `version` field in `package.json`
|
||||
*/
|
||||
export const version: string;
|
||||
|
||||
// https://github.com/prettier/prettier/blob/main/src/utilities/public.js
|
||||
export namespace util {
|
||||
interface SkipOptions {
|
||||
backwards?: boolean | undefined;
|
||||
}
|
||||
|
||||
type Quote = "'" | '"';
|
||||
|
||||
function getMaxContinuousCount(text: string, searchString: string): number;
|
||||
|
||||
function getStringWidth(text: string): number;
|
||||
|
||||
function getAlignmentSize(
|
||||
text: string,
|
||||
tabWidth: number,
|
||||
startIndex?: number | undefined,
|
||||
): number;
|
||||
|
||||
function getIndentSize(value: string, tabWidth: number): number;
|
||||
|
||||
function skipNewline(
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions | undefined,
|
||||
): number | false;
|
||||
|
||||
function skipInlineComment(
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
): number | false;
|
||||
|
||||
function skipTrailingComment(
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
): number | false;
|
||||
|
||||
function skipTrailingComment(
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
): number | false;
|
||||
|
||||
function hasNewline(
|
||||
text: string,
|
||||
startIndex: number,
|
||||
options?: SkipOptions | undefined,
|
||||
): boolean;
|
||||
|
||||
function hasNewlineInRange(
|
||||
text: string,
|
||||
startIndex: number,
|
||||
endIndex: number,
|
||||
): boolean;
|
||||
|
||||
function hasSpaces(
|
||||
text: string,
|
||||
startIndex: number,
|
||||
options?: SkipOptions | undefined,
|
||||
): boolean;
|
||||
|
||||
function getNextNonSpaceNonCommentCharacterIndex(
|
||||
text: string,
|
||||
startIndex: number,
|
||||
): number | false;
|
||||
|
||||
function getNextNonSpaceNonCommentCharacter(
|
||||
text: string,
|
||||
startIndex: number,
|
||||
): string;
|
||||
|
||||
function isNextLineEmpty(text: string, startIndex: number): boolean;
|
||||
|
||||
function isPreviousLineEmpty(text: string, startIndex: number): boolean;
|
||||
|
||||
function makeString(
|
||||
rawText: string,
|
||||
enclosingQuote: Quote,
|
||||
unescapeUnnecessaryEscapes?: boolean | undefined,
|
||||
): string;
|
||||
|
||||
function skip(
|
||||
characters: string | RegExp,
|
||||
): (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions,
|
||||
) => number | false;
|
||||
|
||||
const skipWhitespace: (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions,
|
||||
) => number | false;
|
||||
|
||||
const skipSpaces: (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions,
|
||||
) => number | false;
|
||||
|
||||
const skipToLineEnd: (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions,
|
||||
) => number | false;
|
||||
|
||||
const skipEverythingButNewLine: (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions,
|
||||
) => number | false;
|
||||
|
||||
function addLeadingComment(node: any, comment: any): void;
|
||||
|
||||
function addDanglingComment(node: any, comment: any, marker: any): void;
|
||||
|
||||
function addTrailingComment(node: any, comment: any): void;
|
||||
|
||||
function getPreferredQuote(
|
||||
text: string,
|
||||
preferredQuoteOrPreferSingleQuote: Quote | boolean,
|
||||
): Quote;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,504 @@
|
||||
'use strict';
|
||||
|
||||
var errors = require('@solana/errors');
|
||||
|
||||
// src/add-codec-sentinel.ts
|
||||
|
||||
// src/bytes.ts
|
||||
var mergeBytes = (byteArrays) => {
|
||||
const nonEmptyByteArrays = byteArrays.filter((arr) => arr.length);
|
||||
if (nonEmptyByteArrays.length === 0) {
|
||||
return byteArrays.length ? byteArrays[0] : new Uint8Array();
|
||||
}
|
||||
if (nonEmptyByteArrays.length === 1) {
|
||||
return nonEmptyByteArrays[0];
|
||||
}
|
||||
const totalLength = nonEmptyByteArrays.reduce((total, arr) => total + arr.length, 0);
|
||||
const result = new Uint8Array(totalLength);
|
||||
let offset = 0;
|
||||
nonEmptyByteArrays.forEach((arr) => {
|
||||
result.set(arr, offset);
|
||||
offset += arr.length;
|
||||
});
|
||||
return result;
|
||||
};
|
||||
var padBytes = (bytes, length) => {
|
||||
if (bytes.length >= length) return bytes;
|
||||
const paddedBytes = new Uint8Array(length).fill(0);
|
||||
paddedBytes.set(bytes);
|
||||
return paddedBytes;
|
||||
};
|
||||
var fixBytes = (bytes, length) => padBytes(bytes.length <= length ? bytes : bytes.slice(0, length), length);
|
||||
function containsBytes(data, bytes, offset) {
|
||||
const slice = offset === 0 && data.length === bytes.length ? data : data.slice(offset, offset + bytes.length);
|
||||
if (slice.length !== bytes.length) return false;
|
||||
return bytes.every((b, i) => b === slice[i]);
|
||||
}
|
||||
function getEncodedSize(value, encoder) {
|
||||
return "fixedSize" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);
|
||||
}
|
||||
function createEncoder(encoder) {
|
||||
return Object.freeze({
|
||||
...encoder,
|
||||
encode: (value) => {
|
||||
const bytes = new Uint8Array(getEncodedSize(value, encoder));
|
||||
encoder.write(value, bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function createDecoder(decoder) {
|
||||
return Object.freeze({
|
||||
...decoder,
|
||||
decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0]
|
||||
});
|
||||
}
|
||||
function createCodec(codec) {
|
||||
return Object.freeze({
|
||||
...codec,
|
||||
decode: (bytes, offset = 0) => codec.read(bytes, offset)[0],
|
||||
encode: (value) => {
|
||||
const bytes = new Uint8Array(getEncodedSize(value, codec));
|
||||
codec.write(value, bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function isFixedSize(codec) {
|
||||
return "fixedSize" in codec && typeof codec.fixedSize === "number";
|
||||
}
|
||||
function assertIsFixedSize(codec) {
|
||||
if (!isFixedSize(codec)) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_FIXED_LENGTH);
|
||||
}
|
||||
}
|
||||
function isVariableSize(codec) {
|
||||
return !isFixedSize(codec);
|
||||
}
|
||||
function assertIsVariableSize(codec) {
|
||||
if (!isVariableSize(codec)) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_VARIABLE_LENGTH);
|
||||
}
|
||||
}
|
||||
function combineCodec(encoder, decoder) {
|
||||
if (isFixedSize(encoder) !== isFixedSize(decoder)) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__ENCODER_DECODER_SIZE_COMPATIBILITY_MISMATCH);
|
||||
}
|
||||
if (isFixedSize(encoder) && isFixedSize(decoder) && encoder.fixedSize !== decoder.fixedSize) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__ENCODER_DECODER_FIXED_SIZE_MISMATCH, {
|
||||
decoderFixedSize: decoder.fixedSize,
|
||||
encoderFixedSize: encoder.fixedSize
|
||||
});
|
||||
}
|
||||
if (!isFixedSize(encoder) && !isFixedSize(decoder) && encoder.maxSize !== decoder.maxSize) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__ENCODER_DECODER_MAX_SIZE_MISMATCH, {
|
||||
decoderMaxSize: decoder.maxSize,
|
||||
encoderMaxSize: encoder.maxSize
|
||||
});
|
||||
}
|
||||
return {
|
||||
...decoder,
|
||||
...encoder,
|
||||
decode: decoder.decode,
|
||||
encode: encoder.encode,
|
||||
read: decoder.read,
|
||||
write: encoder.write
|
||||
};
|
||||
}
|
||||
|
||||
// src/add-codec-sentinel.ts
|
||||
function addEncoderSentinel(encoder, sentinel) {
|
||||
const write = (value, bytes, offset) => {
|
||||
const encoderBytes = encoder.encode(value);
|
||||
if (findSentinelIndex(encoderBytes, sentinel) >= 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__ENCODED_BYTES_MUST_NOT_INCLUDE_SENTINEL, {
|
||||
encodedBytes: encoderBytes,
|
||||
hexEncodedBytes: hexBytes(encoderBytes),
|
||||
hexSentinel: hexBytes(sentinel),
|
||||
sentinel
|
||||
});
|
||||
}
|
||||
bytes.set(encoderBytes, offset);
|
||||
offset += encoderBytes.length;
|
||||
bytes.set(sentinel, offset);
|
||||
offset += sentinel.length;
|
||||
return offset;
|
||||
};
|
||||
if (isFixedSize(encoder)) {
|
||||
return createEncoder({ ...encoder, fixedSize: encoder.fixedSize + sentinel.length, write });
|
||||
}
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
...encoder.maxSize != null ? { maxSize: encoder.maxSize + sentinel.length } : {},
|
||||
getSizeFromValue: (value) => encoder.getSizeFromValue(value) + sentinel.length,
|
||||
write
|
||||
});
|
||||
}
|
||||
function addDecoderSentinel(decoder, sentinel) {
|
||||
const read = (bytes, offset) => {
|
||||
const candidateBytes = offset === 0 ? bytes : bytes.slice(offset);
|
||||
const sentinelIndex = findSentinelIndex(candidateBytes, sentinel);
|
||||
if (sentinelIndex === -1) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__SENTINEL_MISSING_IN_DECODED_BYTES, {
|
||||
decodedBytes: candidateBytes,
|
||||
hexDecodedBytes: hexBytes(candidateBytes),
|
||||
hexSentinel: hexBytes(sentinel),
|
||||
sentinel
|
||||
});
|
||||
}
|
||||
const preSentinelBytes = candidateBytes.slice(0, sentinelIndex);
|
||||
return [decoder.decode(preSentinelBytes), offset + preSentinelBytes.length + sentinel.length];
|
||||
};
|
||||
if (isFixedSize(decoder)) {
|
||||
return createDecoder({ ...decoder, fixedSize: decoder.fixedSize + sentinel.length, read });
|
||||
}
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
...decoder.maxSize != null ? { maxSize: decoder.maxSize + sentinel.length } : {},
|
||||
read
|
||||
});
|
||||
}
|
||||
function addCodecSentinel(codec, sentinel) {
|
||||
return combineCodec(addEncoderSentinel(codec, sentinel), addDecoderSentinel(codec, sentinel));
|
||||
}
|
||||
function findSentinelIndex(bytes, sentinel) {
|
||||
return bytes.findIndex((byte, index, arr) => {
|
||||
if (sentinel.length === 1) return byte === sentinel[0];
|
||||
return containsBytes(arr, sentinel, index);
|
||||
});
|
||||
}
|
||||
function hexBytes(bytes) {
|
||||
return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
|
||||
}
|
||||
function assertByteArrayIsNotEmptyForCodec(codecDescription, bytes, offset = 0) {
|
||||
if (bytes.length - offset <= 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__CANNOT_DECODE_EMPTY_BYTE_ARRAY, {
|
||||
codecDescription
|
||||
});
|
||||
}
|
||||
}
|
||||
function assertByteArrayHasEnoughBytesForCodec(codecDescription, expected, bytes, offset = 0) {
|
||||
const bytesLength = bytes.length - offset;
|
||||
if (bytesLength < expected) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__INVALID_BYTE_LENGTH, {
|
||||
bytesLength,
|
||||
codecDescription,
|
||||
expected
|
||||
});
|
||||
}
|
||||
}
|
||||
function assertByteArrayOffsetIsNotOutOfRange(codecDescription, offset, bytesLength) {
|
||||
if (offset < 0 || offset > bytesLength) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__OFFSET_OUT_OF_RANGE, {
|
||||
bytesLength,
|
||||
codecDescription,
|
||||
offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// src/add-codec-size-prefix.ts
|
||||
function addEncoderSizePrefix(encoder, prefix) {
|
||||
const write = (value, bytes, offset) => {
|
||||
const encoderBytes = encoder.encode(value);
|
||||
offset = prefix.write(encoderBytes.length, bytes, offset);
|
||||
bytes.set(encoderBytes, offset);
|
||||
return offset + encoderBytes.length;
|
||||
};
|
||||
if (isFixedSize(prefix) && isFixedSize(encoder)) {
|
||||
return createEncoder({ ...encoder, fixedSize: prefix.fixedSize + encoder.fixedSize, write });
|
||||
}
|
||||
const prefixMaxSize = isFixedSize(prefix) ? prefix.fixedSize : prefix.maxSize ?? null;
|
||||
const encoderMaxSize = isFixedSize(encoder) ? encoder.fixedSize : encoder.maxSize ?? null;
|
||||
const maxSize = prefixMaxSize !== null && encoderMaxSize !== null ? prefixMaxSize + encoderMaxSize : null;
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
...maxSize !== null ? { maxSize } : {},
|
||||
getSizeFromValue: (value) => {
|
||||
const encoderSize = getEncodedSize(value, encoder);
|
||||
return getEncodedSize(encoderSize, prefix) + encoderSize;
|
||||
},
|
||||
write
|
||||
});
|
||||
}
|
||||
function addDecoderSizePrefix(decoder, prefix) {
|
||||
const read = (bytes, offset) => {
|
||||
const [bigintSize, decoderOffset] = prefix.read(bytes, offset);
|
||||
const size = Number(bigintSize);
|
||||
offset = decoderOffset;
|
||||
if (offset > 0 || bytes.length > size) {
|
||||
bytes = bytes.slice(offset, offset + size);
|
||||
}
|
||||
assertByteArrayHasEnoughBytesForCodec("addDecoderSizePrefix", size, bytes);
|
||||
return [decoder.decode(bytes), offset + size];
|
||||
};
|
||||
if (isFixedSize(prefix) && isFixedSize(decoder)) {
|
||||
return createDecoder({ ...decoder, fixedSize: prefix.fixedSize + decoder.fixedSize, read });
|
||||
}
|
||||
const prefixMaxSize = isFixedSize(prefix) ? prefix.fixedSize : prefix.maxSize ?? null;
|
||||
const decoderMaxSize = isFixedSize(decoder) ? decoder.fixedSize : decoder.maxSize ?? null;
|
||||
const maxSize = prefixMaxSize !== null && decoderMaxSize !== null ? prefixMaxSize + decoderMaxSize : null;
|
||||
return createDecoder({ ...decoder, ...maxSize !== null ? { maxSize } : {}, read });
|
||||
}
|
||||
function addCodecSizePrefix(codec, prefix) {
|
||||
return combineCodec(addEncoderSizePrefix(codec, prefix), addDecoderSizePrefix(codec, prefix));
|
||||
}
|
||||
|
||||
// src/fix-codec-size.ts
|
||||
function fixEncoderSize(encoder, fixedBytes) {
|
||||
return createEncoder({
|
||||
fixedSize: fixedBytes,
|
||||
write: (value, bytes, offset) => {
|
||||
const variableByteArray = encoder.encode(value);
|
||||
const fixedByteArray = variableByteArray.length > fixedBytes ? variableByteArray.slice(0, fixedBytes) : variableByteArray;
|
||||
bytes.set(fixedByteArray, offset);
|
||||
return offset + fixedBytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function fixDecoderSize(decoder, fixedBytes) {
|
||||
return createDecoder({
|
||||
fixedSize: fixedBytes,
|
||||
read: (bytes, offset) => {
|
||||
assertByteArrayHasEnoughBytesForCodec("fixCodecSize", fixedBytes, bytes, offset);
|
||||
if (offset > 0 || bytes.length > fixedBytes) {
|
||||
bytes = bytes.slice(offset, offset + fixedBytes);
|
||||
}
|
||||
if (isFixedSize(decoder)) {
|
||||
bytes = fixBytes(bytes, decoder.fixedSize);
|
||||
}
|
||||
const [value] = decoder.read(bytes, 0);
|
||||
return [value, offset + fixedBytes];
|
||||
}
|
||||
});
|
||||
}
|
||||
function fixCodecSize(codec, fixedBytes) {
|
||||
return combineCodec(fixEncoderSize(codec, fixedBytes), fixDecoderSize(codec, fixedBytes));
|
||||
}
|
||||
|
||||
// src/offset-codec.ts
|
||||
function offsetEncoder(encoder, config) {
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
write: (value, bytes, preOffset) => {
|
||||
const wrapBytes = (offset) => modulo(offset, bytes.length);
|
||||
const newPreOffset = config.preOffset ? config.preOffset({ bytes, preOffset, wrapBytes }) : preOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetEncoder", newPreOffset, bytes.length);
|
||||
const postOffset = encoder.write(value, bytes, newPreOffset);
|
||||
const newPostOffset = config.postOffset ? config.postOffset({ bytes, newPreOffset, postOffset, preOffset, wrapBytes }) : postOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetEncoder", newPostOffset, bytes.length);
|
||||
return newPostOffset;
|
||||
}
|
||||
});
|
||||
}
|
||||
function offsetDecoder(decoder, config) {
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, preOffset) => {
|
||||
const wrapBytes = (offset) => modulo(offset, bytes.length);
|
||||
const newPreOffset = config.preOffset ? config.preOffset({ bytes, preOffset, wrapBytes }) : preOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetDecoder", newPreOffset, bytes.length);
|
||||
const [value, postOffset] = decoder.read(bytes, newPreOffset);
|
||||
const newPostOffset = config.postOffset ? config.postOffset({ bytes, newPreOffset, postOffset, preOffset, wrapBytes }) : postOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetDecoder", newPostOffset, bytes.length);
|
||||
return [value, newPostOffset];
|
||||
}
|
||||
});
|
||||
}
|
||||
function offsetCodec(codec, config) {
|
||||
return combineCodec(offsetEncoder(codec, config), offsetDecoder(codec, config));
|
||||
}
|
||||
function modulo(dividend, divisor) {
|
||||
if (divisor === 0) return 0;
|
||||
return (dividend % divisor + divisor) % divisor;
|
||||
}
|
||||
function resizeEncoder(encoder, resize) {
|
||||
if (isFixedSize(encoder)) {
|
||||
const fixedSize = resize(encoder.fixedSize);
|
||||
if (fixedSize < 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: fixedSize,
|
||||
codecDescription: "resizeEncoder"
|
||||
});
|
||||
}
|
||||
return createEncoder({ ...encoder, fixedSize });
|
||||
}
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
getSizeFromValue: (value) => {
|
||||
const newSize = resize(encoder.getSizeFromValue(value));
|
||||
if (newSize < 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: newSize,
|
||||
codecDescription: "resizeEncoder"
|
||||
});
|
||||
}
|
||||
return newSize;
|
||||
}
|
||||
});
|
||||
}
|
||||
function resizeDecoder(decoder, resize) {
|
||||
if (isFixedSize(decoder)) {
|
||||
const fixedSize = resize(decoder.fixedSize);
|
||||
if (fixedSize < 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: fixedSize,
|
||||
codecDescription: "resizeDecoder"
|
||||
});
|
||||
}
|
||||
return createDecoder({ ...decoder, fixedSize });
|
||||
}
|
||||
return decoder;
|
||||
}
|
||||
function resizeCodec(codec, resize) {
|
||||
return combineCodec(resizeEncoder(codec, resize), resizeDecoder(codec, resize));
|
||||
}
|
||||
|
||||
// src/pad-codec.ts
|
||||
function padLeftEncoder(encoder, offset) {
|
||||
return offsetEncoder(
|
||||
resizeEncoder(encoder, (size) => size + offset),
|
||||
{ preOffset: ({ preOffset }) => preOffset + offset }
|
||||
);
|
||||
}
|
||||
function padRightEncoder(encoder, offset) {
|
||||
return offsetEncoder(
|
||||
resizeEncoder(encoder, (size) => size + offset),
|
||||
{ postOffset: ({ postOffset }) => postOffset + offset }
|
||||
);
|
||||
}
|
||||
function padLeftDecoder(decoder, offset) {
|
||||
return offsetDecoder(
|
||||
resizeDecoder(decoder, (size) => size + offset),
|
||||
{ preOffset: ({ preOffset }) => preOffset + offset }
|
||||
);
|
||||
}
|
||||
function padRightDecoder(decoder, offset) {
|
||||
return offsetDecoder(
|
||||
resizeDecoder(decoder, (size) => size + offset),
|
||||
{ postOffset: ({ postOffset }) => postOffset + offset }
|
||||
);
|
||||
}
|
||||
function padLeftCodec(codec, offset) {
|
||||
return combineCodec(padLeftEncoder(codec, offset), padLeftDecoder(codec, offset));
|
||||
}
|
||||
function padRightCodec(codec, offset) {
|
||||
return combineCodec(padRightEncoder(codec, offset), padRightDecoder(codec, offset));
|
||||
}
|
||||
|
||||
// src/reverse-codec.ts
|
||||
function copySourceToTargetInReverse(source, target_WILL_MUTATE, sourceOffset, sourceLength, targetOffset = 0) {
|
||||
while (sourceOffset < --sourceLength) {
|
||||
const leftValue = source[sourceOffset];
|
||||
target_WILL_MUTATE[sourceOffset + targetOffset] = source[sourceLength];
|
||||
target_WILL_MUTATE[sourceLength + targetOffset] = leftValue;
|
||||
sourceOffset++;
|
||||
}
|
||||
if (sourceOffset === sourceLength) {
|
||||
target_WILL_MUTATE[sourceOffset + targetOffset] = source[sourceOffset];
|
||||
}
|
||||
}
|
||||
function reverseEncoder(encoder) {
|
||||
assertIsFixedSize(encoder);
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
write: (value, bytes, offset) => {
|
||||
const newOffset = encoder.write(value, bytes, offset);
|
||||
copySourceToTargetInReverse(
|
||||
bytes,
|
||||
bytes,
|
||||
offset,
|
||||
offset + encoder.fixedSize
|
||||
);
|
||||
return newOffset;
|
||||
}
|
||||
});
|
||||
}
|
||||
function reverseDecoder(decoder) {
|
||||
assertIsFixedSize(decoder);
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, offset) => {
|
||||
const reversedBytes = bytes.slice();
|
||||
copySourceToTargetInReverse(
|
||||
bytes,
|
||||
reversedBytes,
|
||||
offset,
|
||||
offset + decoder.fixedSize
|
||||
);
|
||||
return decoder.read(reversedBytes, offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
function reverseCodec(codec) {
|
||||
return combineCodec(reverseEncoder(codec), reverseDecoder(codec));
|
||||
}
|
||||
|
||||
// src/transform-codec.ts
|
||||
function transformEncoder(encoder, unmap) {
|
||||
return createEncoder({
|
||||
...isVariableSize(encoder) ? { ...encoder, getSizeFromValue: (value) => encoder.getSizeFromValue(unmap(value)) } : encoder,
|
||||
write: (value, bytes, offset) => encoder.write(unmap(value), bytes, offset)
|
||||
});
|
||||
}
|
||||
function transformDecoder(decoder, map) {
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, offset) => {
|
||||
const [value, newOffset] = decoder.read(bytes, offset);
|
||||
return [map(value, bytes, offset), newOffset];
|
||||
}
|
||||
});
|
||||
}
|
||||
function transformCodec(codec, unmap, map) {
|
||||
return createCodec({
|
||||
...transformEncoder(codec, unmap),
|
||||
read: map ? transformDecoder(codec, map).read : codec.read
|
||||
});
|
||||
}
|
||||
|
||||
exports.addCodecSentinel = addCodecSentinel;
|
||||
exports.addCodecSizePrefix = addCodecSizePrefix;
|
||||
exports.addDecoderSentinel = addDecoderSentinel;
|
||||
exports.addDecoderSizePrefix = addDecoderSizePrefix;
|
||||
exports.addEncoderSentinel = addEncoderSentinel;
|
||||
exports.addEncoderSizePrefix = addEncoderSizePrefix;
|
||||
exports.assertByteArrayHasEnoughBytesForCodec = assertByteArrayHasEnoughBytesForCodec;
|
||||
exports.assertByteArrayIsNotEmptyForCodec = assertByteArrayIsNotEmptyForCodec;
|
||||
exports.assertByteArrayOffsetIsNotOutOfRange = assertByteArrayOffsetIsNotOutOfRange;
|
||||
exports.assertIsFixedSize = assertIsFixedSize;
|
||||
exports.assertIsVariableSize = assertIsVariableSize;
|
||||
exports.combineCodec = combineCodec;
|
||||
exports.containsBytes = containsBytes;
|
||||
exports.createCodec = createCodec;
|
||||
exports.createDecoder = createDecoder;
|
||||
exports.createEncoder = createEncoder;
|
||||
exports.fixBytes = fixBytes;
|
||||
exports.fixCodecSize = fixCodecSize;
|
||||
exports.fixDecoderSize = fixDecoderSize;
|
||||
exports.fixEncoderSize = fixEncoderSize;
|
||||
exports.getEncodedSize = getEncodedSize;
|
||||
exports.isFixedSize = isFixedSize;
|
||||
exports.isVariableSize = isVariableSize;
|
||||
exports.mergeBytes = mergeBytes;
|
||||
exports.offsetCodec = offsetCodec;
|
||||
exports.offsetDecoder = offsetDecoder;
|
||||
exports.offsetEncoder = offsetEncoder;
|
||||
exports.padBytes = padBytes;
|
||||
exports.padLeftCodec = padLeftCodec;
|
||||
exports.padLeftDecoder = padLeftDecoder;
|
||||
exports.padLeftEncoder = padLeftEncoder;
|
||||
exports.padRightCodec = padRightCodec;
|
||||
exports.padRightDecoder = padRightDecoder;
|
||||
exports.padRightEncoder = padRightEncoder;
|
||||
exports.resizeCodec = resizeCodec;
|
||||
exports.resizeDecoder = resizeDecoder;
|
||||
exports.resizeEncoder = resizeEncoder;
|
||||
exports.reverseCodec = reverseCodec;
|
||||
exports.reverseDecoder = reverseDecoder;
|
||||
exports.reverseEncoder = reverseEncoder;
|
||||
exports.transformCodec = transformCodec;
|
||||
exports.transformDecoder = transformDecoder;
|
||||
exports.transformEncoder = transformEncoder;
|
||||
//# sourceMappingURL=index.node.cjs.map
|
||||
//# sourceMappingURL=index.node.cjs.map
|
||||
@@ -0,0 +1,72 @@
|
||||
// Interface declaration for Float16Array, required in @types/node v24+.
|
||||
// These definitions are specific to TS 5.7.
|
||||
|
||||
// This needs all of the "common" properties/methods of the TypedArrays,
|
||||
// otherwise the type unions `TypedArray` and `ArrayBufferView` will be
|
||||
// empty objects.
|
||||
interface Float16Array<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> {
|
||||
readonly BYTES_PER_ELEMENT: number;
|
||||
readonly buffer: TArrayBuffer;
|
||||
readonly byteLength: number;
|
||||
readonly byteOffset: number;
|
||||
readonly length: number;
|
||||
readonly [Symbol.toStringTag]: "Float16Array";
|
||||
at(index: number): number | undefined;
|
||||
copyWithin(target: number, start: number, end?: number): this;
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
every(predicate: (value: number, index: number, array: this) => unknown, thisArg?: any): boolean;
|
||||
fill(value: number, start?: number, end?: number): this;
|
||||
filter(predicate: (value: number, index: number, array: this) => any, thisArg?: any): Float16Array<ArrayBuffer>;
|
||||
find(predicate: (value: number, index: number, obj: this) => boolean, thisArg?: any): number | undefined;
|
||||
findIndex(predicate: (value: number, index: number, obj: this) => boolean, thisArg?: any): number;
|
||||
findLast<S extends number>(
|
||||
predicate: (value: number, index: number, array: this) => value is S,
|
||||
thisArg?: any,
|
||||
): S | undefined;
|
||||
findLast(predicate: (value: number, index: number, array: this) => unknown, thisArg?: any): number | undefined;
|
||||
findLastIndex(predicate: (value: number, index: number, array: this) => unknown, thisArg?: any): number;
|
||||
forEach(callbackfn: (value: number, index: number, array: this) => void, thisArg?: any): void;
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
indexOf(searchElement: number, fromIndex?: number): number;
|
||||
join(separator?: string): string;
|
||||
keys(): ArrayIterator<number>;
|
||||
lastIndexOf(searchElement: number, fromIndex?: number): number;
|
||||
map(callbackfn: (value: number, index: number, array: this) => number, thisArg?: any): Float16Array<ArrayBuffer>;
|
||||
reduce(
|
||||
callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: this) => number,
|
||||
): number;
|
||||
reduce(
|
||||
callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: this) => number,
|
||||
initialValue: number,
|
||||
): number;
|
||||
reduce<U>(
|
||||
callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: this) => U,
|
||||
initialValue: U,
|
||||
): U;
|
||||
reduceRight(
|
||||
callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: this) => number,
|
||||
): number;
|
||||
reduceRight(
|
||||
callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: this) => number,
|
||||
initialValue: number,
|
||||
): number;
|
||||
reduceRight<U>(
|
||||
callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: this) => U,
|
||||
initialValue: U,
|
||||
): U;
|
||||
reverse(): this;
|
||||
set(array: ArrayLike<number>, offset?: number): void;
|
||||
slice(start?: number, end?: number): Float16Array<ArrayBuffer>;
|
||||
some(predicate: (value: number, index: number, array: this) => unknown, thisArg?: any): boolean;
|
||||
sort(compareFn?: (a: number, b: number) => number): this;
|
||||
subarray(begin?: number, end?: number): Float16Array<TArrayBuffer>;
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
toReversed(): Float16Array<ArrayBuffer>;
|
||||
toSorted(compareFn?: (a: number, b: number) => number): Float16Array<ArrayBuffer>;
|
||||
toString(): string;
|
||||
valueOf(): this;
|
||||
values(): ArrayIterator<number>;
|
||||
with(index: number, value: number): Float16Array<ArrayBuffer>;
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
[index: number]: number;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
"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;
|
||||
};
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.coerce = exports.iso = exports.ZodISODuration = exports.ZodISOTime = exports.ZodISODate = exports.ZodISODateTime = exports.locales = exports.fromJSONSchema = exports.toJSONSchema = exports.NEVER = exports.util = exports.TimePrecision = exports.flattenError = exports.formatError = exports.prettifyError = exports.treeifyError = exports.regexes = exports.clone = exports.$brand = exports.$input = exports.$output = exports.config = exports.registry = exports.globalRegistry = exports.core = void 0;
|
||||
exports.core = __importStar(require("../core/index.cjs"));
|
||||
__exportStar(require("./schemas.cjs"), exports);
|
||||
__exportStar(require("./checks.cjs"), exports);
|
||||
__exportStar(require("./errors.cjs"), exports);
|
||||
__exportStar(require("./parse.cjs"), exports);
|
||||
__exportStar(require("./compat.cjs"), exports);
|
||||
// zod-specified
|
||||
const index_js_1 = require("../core/index.cjs");
|
||||
const en_js_1 = __importDefault(require("../locales/en.cjs"));
|
||||
(0, index_js_1.config)((0, en_js_1.default)());
|
||||
var index_js_2 = require("../core/index.cjs");
|
||||
Object.defineProperty(exports, "globalRegistry", { enumerable: true, get: function () { return index_js_2.globalRegistry; } });
|
||||
Object.defineProperty(exports, "registry", { enumerable: true, get: function () { return index_js_2.registry; } });
|
||||
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return index_js_2.config; } });
|
||||
Object.defineProperty(exports, "$output", { enumerable: true, get: function () { return index_js_2.$output; } });
|
||||
Object.defineProperty(exports, "$input", { enumerable: true, get: function () { return index_js_2.$input; } });
|
||||
Object.defineProperty(exports, "$brand", { enumerable: true, get: function () { return index_js_2.$brand; } });
|
||||
Object.defineProperty(exports, "clone", { enumerable: true, get: function () { return index_js_2.clone; } });
|
||||
Object.defineProperty(exports, "regexes", { enumerable: true, get: function () { return index_js_2.regexes; } });
|
||||
Object.defineProperty(exports, "treeifyError", { enumerable: true, get: function () { return index_js_2.treeifyError; } });
|
||||
Object.defineProperty(exports, "prettifyError", { enumerable: true, get: function () { return index_js_2.prettifyError; } });
|
||||
Object.defineProperty(exports, "formatError", { enumerable: true, get: function () { return index_js_2.formatError; } });
|
||||
Object.defineProperty(exports, "flattenError", { enumerable: true, get: function () { return index_js_2.flattenError; } });
|
||||
Object.defineProperty(exports, "TimePrecision", { enumerable: true, get: function () { return index_js_2.TimePrecision; } });
|
||||
Object.defineProperty(exports, "util", { enumerable: true, get: function () { return index_js_2.util; } });
|
||||
Object.defineProperty(exports, "NEVER", { enumerable: true, get: function () { return index_js_2.NEVER; } });
|
||||
var json_schema_processors_js_1 = require("../core/json-schema-processors.cjs");
|
||||
Object.defineProperty(exports, "toJSONSchema", { enumerable: true, get: function () { return json_schema_processors_js_1.toJSONSchema; } });
|
||||
var from_json_schema_js_1 = require("./from-json-schema.cjs");
|
||||
Object.defineProperty(exports, "fromJSONSchema", { enumerable: true, get: function () { return from_json_schema_js_1.fromJSONSchema; } });
|
||||
exports.locales = __importStar(require("../locales/index.cjs"));
|
||||
// iso
|
||||
// must be exported from top-level
|
||||
// https://github.com/colinhacks/zod/issues/4491
|
||||
var iso_js_1 = require("./iso.cjs");
|
||||
Object.defineProperty(exports, "ZodISODateTime", { enumerable: true, get: function () { return iso_js_1.ZodISODateTime; } });
|
||||
Object.defineProperty(exports, "ZodISODate", { enumerable: true, get: function () { return iso_js_1.ZodISODate; } });
|
||||
Object.defineProperty(exports, "ZodISOTime", { enumerable: true, get: function () { return iso_js_1.ZodISOTime; } });
|
||||
Object.defineProperty(exports, "ZodISODuration", { enumerable: true, get: function () { return iso_js_1.ZodISODuration; } });
|
||||
exports.iso = __importStar(require("./iso.cjs"));
|
||||
exports.coerce = __importStar(require("./coerce.cjs"));
|
||||
@@ -0,0 +1,112 @@
|
||||
// @ts-ignore TS6133
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import { z } from "zod/v3";
|
||||
import { util } from "../helpers/util.js";
|
||||
|
||||
test("basic defaults", () => {
|
||||
expect(z.string().default("default").parse(undefined)).toBe("default");
|
||||
});
|
||||
|
||||
test("default with transform", () => {
|
||||
const stringWithDefault = z
|
||||
.string()
|
||||
.transform((val) => val.toUpperCase())
|
||||
.default("default");
|
||||
expect(stringWithDefault.parse(undefined)).toBe("DEFAULT");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodDefault);
|
||||
expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodEffects);
|
||||
expect(stringWithDefault._def.innerType._def.schema).toBeInstanceOf(z.ZodSchema);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
util.assertEqual<inp, string | undefined>(true);
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
util.assertEqual<out, string>(true);
|
||||
});
|
||||
|
||||
test("default on existing optional", () => {
|
||||
const stringWithDefault = z.string().optional().default("asdf");
|
||||
expect(stringWithDefault.parse(undefined)).toBe("asdf");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodDefault);
|
||||
expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodOptional);
|
||||
expect(stringWithDefault._def.innerType._def.innerType).toBeInstanceOf(z.ZodString);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
util.assertEqual<inp, string | undefined>(true);
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
util.assertEqual<out, string>(true);
|
||||
});
|
||||
|
||||
test("optional on default", () => {
|
||||
const stringWithDefault = z.string().default("asdf").optional();
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
util.assertEqual<inp, string | undefined>(true);
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
util.assertEqual<out, string | undefined>(true);
|
||||
});
|
||||
|
||||
test("complex chain example", () => {
|
||||
const complex = z
|
||||
.string()
|
||||
.default("asdf")
|
||||
.transform((val) => val.toUpperCase())
|
||||
.default("qwer")
|
||||
.removeDefault()
|
||||
.optional()
|
||||
.default("asdfasdf");
|
||||
|
||||
expect(complex.parse(undefined)).toBe("ASDFASDF");
|
||||
});
|
||||
|
||||
test("removeDefault", () => {
|
||||
const stringWithRemovedDefault = z.string().default("asdf").removeDefault();
|
||||
|
||||
type out = z.output<typeof stringWithRemovedDefault>;
|
||||
util.assertEqual<out, string>(true);
|
||||
});
|
||||
|
||||
test("nested", () => {
|
||||
const inner = z.string().default("asdf");
|
||||
const outer = z.object({ inner }).default({
|
||||
inner: undefined,
|
||||
});
|
||||
type input = z.input<typeof outer>;
|
||||
util.assertEqual<input, { inner?: string | undefined } | undefined>(true);
|
||||
type out = z.output<typeof outer>;
|
||||
util.assertEqual<out, { inner: string }>(true);
|
||||
expect(outer.parse(undefined)).toEqual({ inner: "asdf" });
|
||||
expect(outer.parse({})).toEqual({ inner: "asdf" });
|
||||
expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" });
|
||||
});
|
||||
|
||||
test("chained defaults", () => {
|
||||
const stringWithDefault = z.string().default("inner").default("outer");
|
||||
const result = stringWithDefault.parse(undefined);
|
||||
expect(result).toEqual("outer");
|
||||
});
|
||||
|
||||
test("factory", () => {
|
||||
expect(z.ZodDefault.create(z.string(), { default: "asdf" }).parse(undefined)).toEqual("asdf");
|
||||
});
|
||||
|
||||
test("native enum", () => {
|
||||
enum Fruits {
|
||||
apple = "apple",
|
||||
orange = "orange",
|
||||
}
|
||||
|
||||
const schema = z.object({
|
||||
fruit: z.nativeEnum(Fruits).default(Fruits.apple),
|
||||
});
|
||||
|
||||
expect(schema.parse({})).toEqual({ fruit: Fruits.apple });
|
||||
});
|
||||
|
||||
test("enum", () => {
|
||||
const schema = z.object({
|
||||
fruit: z.enum(["apple", "orange"]).default("apple"),
|
||||
});
|
||||
|
||||
expect(schema.parse({})).toEqual({ fruit: "apple" });
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
function e(e){return e instanceof Error?e.stack||e.message:e}function t(e,t){let n=0;for(let e=0;e<t.length;e++)n=(n<<5)-n+t.charCodeAt(e),n|=0;return e[Math.abs(n)%e.length]}function n(e,t){let n=0,r=0,i=-1,a=0;for(;n<e.length;)if(r<t.length&&(t[r]===e[n]||t[r]===`*`))t[r]===`*`?(i=r,a=n,r++):(n++,r++);else if(i!==-1)r=i+1,a++,n=a;else return!1;for(;r<t.length&&t[r]===`*`;)r++;return r===t.length}function r(e){return e>=1e3?`${(e/1e3).toFixed(1)}s`:`${e}ms`}let i=``;function a(){return i}function o(t,n){let r,a,s,c,l=(...t)=>{if(!l.enabled)return;let i=Date.now(),a=i-(r||i);r=i,t[0]=e(t[0]),typeof t[0]!=`string`&&t.unshift(`%O`);let o=0;t[0]=t[0].replace(/%([a-z%])/gi,(e,r)=>{if(e===`%%`)return`%`;o++;let i=n.formatters[r];if(typeof i==`function`){let n=t[o];e=i.call(l,n),t.splice(o,1),o--}return e}),n.formatArgs.call(l,a,t),l.log(...t)};return l.extend=function(e,t=`:`){return o(this.namespace+t+e,{useColors:this.useColors,color:this.color,formatArgs:this.formatArgs,formatters:this.formatters,inspectOpts:this.inspectOpts,log:this.log,humanize:this.humanize})},Object.assign(l,n),l.namespace=t,Object.defineProperty(l,"enabled",{enumerable:!0,configurable:!1,get:()=>a==null?(s!==i&&(s=i,c=d(t)),c):a,set:e=>{a=e}}),l}let s=[],c=[];function l(e){i=e,s=[],c=[];let t=i.trim().replace(/\s+/g,`,`).split(`,`).filter(Boolean);for(let e of t)e[0]===`-`?c.push(e.slice(1)):s.push(e)}function u(){let e=[...s,...c.map(e=>`-${e}`)].join(`,`);return l(``),e}function d(e){for(let t of c)if(n(e,t))return!1;for(let t of s)if(n(e,t))return!0;return!1}const f=`#0000CC.#0000FF.#0033CC.#0033FF.#0066CC.#0066FF.#0099CC.#0099FF.#00CC00.#00CC33.#00CC66.#00CC99.#00CCCC.#00CCFF.#3300CC.#3300FF.#3333CC.#3333FF.#3366CC.#3366FF.#3399CC.#3399FF.#33CC00.#33CC33.#33CC66.#33CC99.#33CCCC.#33CCFF.#6600CC.#6600FF.#6633CC.#6633FF.#66CC00.#66CC33.#9900CC.#9900FF.#9933CC.#9933FF.#99CC00.#99CC33.#CC0000.#CC0033.#CC0066.#CC0099.#CC00CC.#CC00FF.#CC3300.#CC3333.#CC3366.#CC3399.#CC33CC.#CC33FF.#CC6600.#CC6633.#CC9900.#CC9933.#CCCC00.#CCCC33.#FF0000.#FF0033.#FF0066.#FF0099.#FF00CC.#FF00FF.#FF3300.#FF3333.#FF3366.#FF3399.#FF33CC.#FF33FF.#FF6600.#FF6633.#FF9900.#FF9933.#FFCC00.#FFCC33`.split(`.`);function p(e,t){let{useColors:n}=this;if(t[0]=`${(n?`%c`:``)+this.namespace+(n?` %c`:` `)+t[0]+(n?`%c `:` `)}+${this.humanize(e)}`,!n)return;let r=`color: ${this.color}`;t.splice(1,0,r,`color: inherit`);let i=0,a=0;t[0].replace(/%[a-z%]/gi,e=>{e!==`%%`&&(i++,e===`%c`&&(a=i))}),t.splice(a,0,r)}const m=console.debug||console.log||(()=>{}),h=v(),g={useColors:!0,formatArgs:p,formatters:{j(e){try{return JSON.stringify(e)}catch(e){return`[UnexpectedJSONParseError]: ${e.message}`}}},inspectOpts:{},humanize:r,log:m};function _(e,n){var r;let i=(r=n&&n.color)==null?t(f,e):r;return o(e,Object.assign(g,{color:i},n))}function v(){try{return localStorage}catch(e){}}function y(){let e;try{e=h.getItem(`debug`)||h.getItem(`DEBUG`)}catch(e){}return!e&&typeof process<`u`&&`env`in process&&(e=process.env.DEBUG),e||``}function b(e){try{e?h.setItem(`debug`,e):h.removeItem(`debug`)}catch(e){}}function x(e){b(e),l(e)}l(y());export{_ as createDebug,u as disable,x as enable,d as enabled,a as namespaces};
|
||||
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function (it) {
|
||||
const { pluginName, resolvePluginsRelativeTo, importerName } = it;
|
||||
|
||||
return `
|
||||
ESLint couldn't find the plugin "${pluginName}".
|
||||
|
||||
(The package "${pluginName}" was not found when loaded as a Node module from the directory "${resolvePluginsRelativeTo}".)
|
||||
|
||||
It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:
|
||||
|
||||
npm install ${pluginName}@latest --save-dev
|
||||
|
||||
The plugin "${pluginName}" was referenced from the config file in "${importerName}".
|
||||
|
||||
If you still can't figure out the problem, please see https://eslint.org/docs/latest/use/troubleshooting.
|
||||
`.trimStart();
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "locate-path",
|
||||
"version": "6.0.0",
|
||||
"description": "Get the first path that exists on disk of multiple paths",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/locate-path",
|
||||
"funding": "https://github.com/sponsors/sindresorhus",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "https://sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava && tsd"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts"
|
||||
],
|
||||
"keywords": [
|
||||
"locate",
|
||||
"path",
|
||||
"paths",
|
||||
"file",
|
||||
"files",
|
||||
"exists",
|
||||
"find",
|
||||
"finder",
|
||||
"search",
|
||||
"searcher",
|
||||
"array",
|
||||
"iterable",
|
||||
"iterator"
|
||||
],
|
||||
"dependencies": {
|
||||
"p-locate": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^2.4.0",
|
||||
"tsd": "^0.13.1",
|
||||
"xo": "^0.32.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
help-me
|
||||
=======
|
||||
|
||||
Help command for node, to use with [minimist](http://npm.im/minimist) and [commist](http://npm.im/commist).
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```js
|
||||
'use strict'
|
||||
|
||||
var helpMe = require('help-me')
|
||||
var path = require('path')
|
||||
var help = helpMe({
|
||||
dir: path.join(__dirname, 'doc'),
|
||||
// the default
|
||||
ext: '.txt'
|
||||
})
|
||||
|
||||
help
|
||||
.createStream(['hello']) // can support also strings
|
||||
.pipe(process.stdout)
|
||||
|
||||
// little helper to do the same
|
||||
help.toStdout(['hello'])
|
||||
```
|
||||
|
||||
Using ESM and top-level await::
|
||||
|
||||
```js
|
||||
import { help } from 'help-me'
|
||||
import { join } from 'desm'
|
||||
|
||||
await help({
|
||||
dir: join(import.meta.url, 'doc'),
|
||||
// the default
|
||||
ext: '.txt'
|
||||
}, ['hello'])
|
||||
```
|
||||
|
||||
Usage with commist
|
||||
------------------
|
||||
|
||||
[Commist](http://npm.im/commist) provide a command system for node.
|
||||
|
||||
```js
|
||||
var commist = require('commist')()
|
||||
var path = require('path')
|
||||
var help = require('help-me')({
|
||||
dir: path.join(__dirname, 'doc')
|
||||
})
|
||||
|
||||
commist.register('help', help.toStdout)
|
||||
|
||||
commist.parse(process.argv.splice(2))
|
||||
```
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
|
||||
This project was kindly sponsored by [nearForm](http://nearform.com).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
@@ -0,0 +1,324 @@
|
||||
/**
|
||||
* @fileoverview Rule to control usage of strict mode directives.
|
||||
* @author Brandon Mills
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets all of the Use Strict Directives in the Directive Prologue of a group of
|
||||
* statements.
|
||||
* @param {ASTNode[]} statements Statements in the program or function body.
|
||||
* @returns {ASTNode[]} All of the Use Strict Directives.
|
||||
*/
|
||||
function getUseStrictDirectives(statements) {
|
||||
const directives = [];
|
||||
|
||||
for (let i = 0; i < statements.length; i++) {
|
||||
const statement = statements[i];
|
||||
|
||||
if (
|
||||
statement.type === "ExpressionStatement" &&
|
||||
statement.expression.type === "Literal" &&
|
||||
statement.expression.value === "use strict"
|
||||
) {
|
||||
directives[i] = statement;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return directives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given parameter is a simple parameter.
|
||||
* @param {ASTNode} node A pattern node to check.
|
||||
* @returns {boolean} `true` if the node is an Identifier node.
|
||||
*/
|
||||
function isSimpleParameter(node) {
|
||||
return node.type === "Identifier";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given parameter list is a simple parameter list.
|
||||
* @param {ASTNode[]} params A parameter list to check.
|
||||
* @returns {boolean} `true` if the every parameter is an Identifier node.
|
||||
*/
|
||||
function isSimpleParameterList(params) {
|
||||
return params.every(isSimpleParameter);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: ["safe"],
|
||||
|
||||
docs: {
|
||||
description: "Require or disallow strict mode directives",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/strict",
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
enum: ["never", "global", "function", "safe"],
|
||||
},
|
||||
],
|
||||
|
||||
fixable: "code",
|
||||
messages: {
|
||||
function: "Use the function form of 'use strict'.",
|
||||
global: "Use the global form of 'use strict'.",
|
||||
multiple: "Multiple 'use strict' directives.",
|
||||
never: "Strict mode is not permitted.",
|
||||
unnecessary: "Unnecessary 'use strict' directive.",
|
||||
module: "'use strict' is unnecessary inside of modules.",
|
||||
implied:
|
||||
"'use strict' is unnecessary when implied strict mode is enabled.",
|
||||
unnecessaryInClasses:
|
||||
"'use strict' is unnecessary inside of classes.",
|
||||
nonSimpleParameterList:
|
||||
"'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016.",
|
||||
wrap: "Wrap {{name}} in a function with 'use strict' directive.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const ecmaFeatures =
|
||||
context.languageOptions.parserOptions.ecmaFeatures || {},
|
||||
scopes = [],
|
||||
classScopes = [];
|
||||
let [mode] = context.options;
|
||||
|
||||
if (ecmaFeatures.impliedStrict) {
|
||||
mode = "implied";
|
||||
} else if (mode === "safe") {
|
||||
mode =
|
||||
ecmaFeatures.globalReturn ||
|
||||
context.languageOptions.sourceType === "commonjs"
|
||||
? "global"
|
||||
: "function";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a reported error should be fixed, depending on the error type.
|
||||
* @param {string} errorType The type of error
|
||||
* @returns {boolean} `true` if the reported error should be fixed
|
||||
*/
|
||||
function shouldFix(errorType) {
|
||||
return (
|
||||
errorType === "multiple" ||
|
||||
errorType === "unnecessary" ||
|
||||
errorType === "module" ||
|
||||
errorType === "implied" ||
|
||||
errorType === "unnecessaryInClasses"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a fixer function to remove a given 'use strict' directive.
|
||||
* @param {ASTNode} node The directive that should be removed
|
||||
* @returns {Function} A fixer function
|
||||
*/
|
||||
function getFixFunction(node) {
|
||||
return fixer => fixer.remove(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a slice of an array of nodes with a given message.
|
||||
* @param {ASTNode[]} nodes Nodes.
|
||||
* @param {string} start Index to start from.
|
||||
* @param {string} end Index to end before.
|
||||
* @param {string} messageId Message to display.
|
||||
* @param {boolean} fix `true` if the directive should be fixed (i.e. removed)
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportSlice(nodes, start, end, messageId, fix) {
|
||||
nodes.slice(start, end).forEach(node => {
|
||||
context.report({
|
||||
node,
|
||||
messageId,
|
||||
fix: fix ? getFixFunction(node) : null,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Report all nodes in an array with a given message.
|
||||
* @param {ASTNode[]} nodes Nodes.
|
||||
* @param {string} messageId Message id to display.
|
||||
* @param {boolean} fix `true` if the directive should be fixed (i.e. removed)
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportAll(nodes, messageId, fix) {
|
||||
reportSlice(nodes, 0, nodes.length, messageId, fix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report all nodes in an array, except the first, with a given message.
|
||||
* @param {ASTNode[]} nodes Nodes.
|
||||
* @param {string} messageId Message id to display.
|
||||
* @param {boolean} fix `true` if the directive should be fixed (i.e. removed)
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportAllExceptFirst(nodes, messageId, fix) {
|
||||
reportSlice(nodes, 1, nodes.length, messageId, fix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entering a function in 'function' mode pushes a new nested scope onto the
|
||||
* stack. The new scope is true if the nested function is strict mode code.
|
||||
* @param {ASTNode} node The function declaration or expression.
|
||||
* @param {ASTNode[]} useStrictDirectives The Use Strict Directives of the node.
|
||||
* @returns {void}
|
||||
*/
|
||||
function enterFunctionInFunctionMode(node, useStrictDirectives) {
|
||||
const isInClass = classScopes.length > 0,
|
||||
isParentGlobal =
|
||||
scopes.length === 0 && classScopes.length === 0,
|
||||
isParentStrict = scopes.length > 0 && scopes.at(-1),
|
||||
isStrict = useStrictDirectives.length > 0;
|
||||
|
||||
if (isStrict) {
|
||||
if (!isSimpleParameterList(node.params)) {
|
||||
context.report({
|
||||
node: useStrictDirectives[0],
|
||||
messageId: "nonSimpleParameterList",
|
||||
});
|
||||
} else if (isParentStrict) {
|
||||
context.report({
|
||||
node: useStrictDirectives[0],
|
||||
messageId: "unnecessary",
|
||||
fix: getFixFunction(useStrictDirectives[0]),
|
||||
});
|
||||
} else if (isInClass) {
|
||||
context.report({
|
||||
node: useStrictDirectives[0],
|
||||
messageId: "unnecessaryInClasses",
|
||||
fix: getFixFunction(useStrictDirectives[0]),
|
||||
});
|
||||
}
|
||||
|
||||
reportAllExceptFirst(useStrictDirectives, "multiple", true);
|
||||
} else if (isParentGlobal) {
|
||||
if (isSimpleParameterList(node.params)) {
|
||||
context.report({ node, messageId: "function" });
|
||||
} else {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "wrap",
|
||||
data: { name: astUtils.getFunctionNameWithKind(node) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
scopes.push(isParentStrict || isStrict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exiting a function in 'function' mode pops its scope off the stack.
|
||||
* @returns {void}
|
||||
*/
|
||||
function exitFunctionInFunctionMode() {
|
||||
scopes.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter a function and either:
|
||||
* - Push a new nested scope onto the stack (in 'function' mode).
|
||||
* - Report all the Use Strict Directives (in the other modes).
|
||||
* @param {ASTNode} node The function declaration or expression.
|
||||
* @returns {void}
|
||||
*/
|
||||
function enterFunction(node) {
|
||||
const isBlock = node.body.type === "BlockStatement",
|
||||
useStrictDirectives = isBlock
|
||||
? getUseStrictDirectives(node.body.body)
|
||||
: [];
|
||||
|
||||
if (mode === "function") {
|
||||
enterFunctionInFunctionMode(node, useStrictDirectives);
|
||||
} else if (useStrictDirectives.length > 0) {
|
||||
if (isSimpleParameterList(node.params)) {
|
||||
reportAll(useStrictDirectives, mode, shouldFix(mode));
|
||||
} else {
|
||||
context.report({
|
||||
node: useStrictDirectives[0],
|
||||
messageId: "nonSimpleParameterList",
|
||||
});
|
||||
reportAllExceptFirst(useStrictDirectives, "multiple", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {import('../types').Rule.RuleListener} */
|
||||
const rule = {
|
||||
Program(node) {
|
||||
const useStrictDirectives = getUseStrictDirectives(node.body);
|
||||
|
||||
if (node.sourceType === "module") {
|
||||
mode = "module";
|
||||
}
|
||||
|
||||
if (mode === "global") {
|
||||
if (
|
||||
node.body.length > 0 &&
|
||||
useStrictDirectives.length === 0
|
||||
) {
|
||||
/*
|
||||
* Report the range as v9 does
|
||||
*/
|
||||
context.report({
|
||||
loc: {
|
||||
start: node.body[0].loc.start,
|
||||
end: node.body.at(-1).loc.end,
|
||||
},
|
||||
messageId: "global",
|
||||
});
|
||||
}
|
||||
reportAllExceptFirst(useStrictDirectives, "multiple", true);
|
||||
} else {
|
||||
reportAll(useStrictDirectives, mode, shouldFix(mode));
|
||||
}
|
||||
},
|
||||
FunctionDeclaration: enterFunction,
|
||||
FunctionExpression: enterFunction,
|
||||
ArrowFunctionExpression: enterFunction,
|
||||
};
|
||||
|
||||
if (mode === "function") {
|
||||
Object.assign(rule, {
|
||||
// Inside of class bodies are always strict mode.
|
||||
ClassBody() {
|
||||
classScopes.push(true);
|
||||
},
|
||||
"ClassBody:exit"() {
|
||||
classScopes.pop();
|
||||
},
|
||||
|
||||
"FunctionDeclaration:exit": exitFunctionInFunctionMode,
|
||||
"FunctionExpression:exit": exitFunctionInFunctionMode,
|
||||
"ArrowFunctionExpression:exit": exitFunctionInFunctionMode,
|
||||
});
|
||||
}
|
||||
|
||||
return rule;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_read_only_error.js";
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "bs58",
|
||||
"version": "4.0.1",
|
||||
"description": "Base 58 encoding / decoding",
|
||||
"keywords": [
|
||||
"base58",
|
||||
"bitcoin",
|
||||
"crypto",
|
||||
"crytography",
|
||||
"decode",
|
||||
"decoding",
|
||||
"encode",
|
||||
"encoding",
|
||||
"litecoin"
|
||||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"standard": "*",
|
||||
"tape": "^4.6.3"
|
||||
},
|
||||
"repository": {
|
||||
"url": "https://github.com/cryptocoinjs/bs58",
|
||||
"type": "git"
|
||||
},
|
||||
"files": [
|
||||
"./index.js"
|
||||
],
|
||||
"main": "./index.js",
|
||||
"scripts": {
|
||||
"standard": "standard",
|
||||
"test": "npm run standard && npm run unit",
|
||||
"unit": "tape test/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"base-x": "^3.0.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* @fileoverview Rule to ensure newline per method call when chaining calls
|
||||
* @author Rajendra Patil
|
||||
* @author Burak Yigit Kaya
|
||||
* @deprecated in ESLint v8.53.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: {
|
||||
message: "Formatting rules are being moved out of ESLint core.",
|
||||
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
|
||||
deprecatedSince: "8.53.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
message:
|
||||
"ESLint Stylistic now maintains deprecated stylistic core rules.",
|
||||
url: "https://eslint.style/guide/migration",
|
||||
plugin: {
|
||||
name: "@stylistic/eslint-plugin",
|
||||
url: "https://eslint.style",
|
||||
},
|
||||
rule: {
|
||||
name: "newline-per-chained-call",
|
||||
url: "https://eslint.style/rules/newline-per-chained-call",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "Require a newline after each call in a method chain",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/newline-per-chained-call",
|
||||
},
|
||||
|
||||
fixable: "whitespace",
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
ignoreChainWithDepth: {
|
||||
type: "integer",
|
||||
minimum: 1,
|
||||
maximum: 10,
|
||||
default: 2,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
messages: {
|
||||
expected: "Expected line break before `{{callee}}`.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const options = context.options[0] || {},
|
||||
ignoreChainWithDepth = options.ignoreChainWithDepth || 2;
|
||||
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
/**
|
||||
* Get the prefix of a given MemberExpression node.
|
||||
* If the MemberExpression node is a computed value it returns a
|
||||
* left bracket. If not it returns a period.
|
||||
* @param {ASTNode} node A MemberExpression node to get
|
||||
* @returns {string} The prefix of the node.
|
||||
*/
|
||||
function getPrefix(node) {
|
||||
if (node.computed) {
|
||||
if (node.optional) {
|
||||
return "?.[";
|
||||
}
|
||||
return "[";
|
||||
}
|
||||
if (node.optional) {
|
||||
return "?.";
|
||||
}
|
||||
return ".";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property text of a given MemberExpression node.
|
||||
* If the text is multiline, this returns only the first line.
|
||||
* @param {ASTNode} node A MemberExpression node to get.
|
||||
* @returns {string} The property text of the node.
|
||||
*/
|
||||
function getPropertyText(node) {
|
||||
const prefix = getPrefix(node);
|
||||
const lines = sourceCode
|
||||
.getText(node.property)
|
||||
.split(astUtils.LINEBREAK_MATCHER);
|
||||
const suffix = node.computed && lines.length === 1 ? "]" : "";
|
||||
|
||||
return prefix + lines[0] + suffix;
|
||||
}
|
||||
|
||||
return {
|
||||
"CallExpression:exit"(node) {
|
||||
const callee = astUtils.skipChainExpression(node.callee);
|
||||
|
||||
if (callee.type !== "MemberExpression") {
|
||||
return;
|
||||
}
|
||||
|
||||
let parent = astUtils.skipChainExpression(callee.object);
|
||||
let depth = 1;
|
||||
|
||||
while (parent && parent.callee) {
|
||||
depth += 1;
|
||||
parent = astUtils.skipChainExpression(
|
||||
astUtils.skipChainExpression(parent.callee).object,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
depth > ignoreChainWithDepth &&
|
||||
astUtils.isTokenOnSameLine(callee.object, callee.property)
|
||||
) {
|
||||
const firstTokenAfterObject = sourceCode.getTokenAfter(
|
||||
callee.object,
|
||||
astUtils.isNotClosingParenToken,
|
||||
);
|
||||
|
||||
context.report({
|
||||
node: callee.property,
|
||||
loc: {
|
||||
start: firstTokenAfterObject.loc.start,
|
||||
end: callee.loc.end,
|
||||
},
|
||||
messageId: "expected",
|
||||
data: {
|
||||
callee: getPropertyText(callee),
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextBefore(
|
||||
firstTokenAfterObject,
|
||||
"\n",
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,803 @@
|
||||
/**
|
||||
* @fileoverview The `Config` class
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const { deepMergeArrays } = require("../shared/deep-merge-arrays");
|
||||
const { flatConfigSchema, hasMethod } = require("./flat-config-schema");
|
||||
const { ObjectSchema } = require("@eslint/config-array");
|
||||
const ajvImport = require("../shared/ajv");
|
||||
const ajv = ajvImport();
|
||||
const ruleReplacements = require("../../conf/replacements.json");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @import { RuleDefinition } from "@eslint/core";
|
||||
* @import { Linter } from "eslint";
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Private Members
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// JSON schema that disallows passing any options
|
||||
const noOptionsSchema = Object.freeze({
|
||||
type: "array",
|
||||
minItems: 0,
|
||||
maxItems: 0,
|
||||
});
|
||||
|
||||
const severities = new Map([
|
||||
[0, 0],
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
["off", 0],
|
||||
["warn", 1],
|
||||
["error", 2],
|
||||
]);
|
||||
|
||||
/**
|
||||
* A collection of compiled validators for rules that have already
|
||||
* been validated.
|
||||
* @type {WeakMap}
|
||||
*/
|
||||
const validators = new WeakMap();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Throws a helpful error when a rule cannot be found.
|
||||
* @param {Object} ruleId The rule identifier.
|
||||
* @param {string} ruleId.pluginName The ID of the rule to find.
|
||||
* @param {string} ruleId.ruleName The ID of the rule to find.
|
||||
* @param {Object} config The config to search in.
|
||||
* @throws {TypeError} For missing plugin or rule.
|
||||
* @returns {void}
|
||||
*/
|
||||
function throwRuleNotFoundError({ pluginName, ruleName }, config) {
|
||||
const ruleId = pluginName === "@" ? ruleName : `${pluginName}/${ruleName}`;
|
||||
|
||||
const errorMessageHeader = `Key "rules": Key "${ruleId}"`;
|
||||
|
||||
let errorMessage = `${errorMessageHeader}: Could not find plugin "${pluginName}" in configuration.`;
|
||||
|
||||
const missingPluginErrorMessage = errorMessage;
|
||||
|
||||
// if the plugin exists then we need to check if the rule exists
|
||||
if (config.plugins && config.plugins[pluginName]) {
|
||||
const replacementRuleName = ruleReplacements.rules[ruleName];
|
||||
|
||||
if (pluginName === "@" && replacementRuleName) {
|
||||
errorMessage = `${errorMessageHeader}: Rule "${ruleName}" was removed and replaced by "${replacementRuleName}".`;
|
||||
} else {
|
||||
errorMessage = `${errorMessageHeader}: Could not find "${ruleName}" in plugin "${pluginName}".`;
|
||||
|
||||
// otherwise, let's see if we can find the rule name elsewhere
|
||||
for (const [otherPluginName, otherPlugin] of Object.entries(
|
||||
config.plugins,
|
||||
)) {
|
||||
if (otherPlugin.rules && otherPlugin.rules[ruleName]) {
|
||||
errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// falls through to throw error
|
||||
}
|
||||
|
||||
const error = new TypeError(errorMessage);
|
||||
|
||||
if (errorMessage === missingPluginErrorMessage) {
|
||||
error.messageTemplate = "config-plugin-missing";
|
||||
error.messageData = { pluginName, ruleId };
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
/**
|
||||
* The error type when a rule has an invalid `meta.schema`.
|
||||
*/
|
||||
class InvalidRuleOptionsSchemaError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} ruleId Id of the rule that has an invalid `meta.schema`.
|
||||
* @param {Error} processingError Error caught while processing the `meta.schema`.
|
||||
*/
|
||||
constructor(ruleId, processingError) {
|
||||
super(
|
||||
`Error while processing options validation schema of rule '${ruleId}': ${processingError.message}`,
|
||||
{ cause: processingError },
|
||||
);
|
||||
this.code = "ESLINT_INVALID_RULE_OPTIONS_SCHEMA";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a ruleId into its plugin and rule parts.
|
||||
* @param {string} ruleId The rule ID to parse.
|
||||
* @returns {{pluginName:string,ruleName:string}} The plugin and rule
|
||||
* parts of the ruleId;
|
||||
*/
|
||||
function parseRuleId(ruleId) {
|
||||
let pluginName, ruleName;
|
||||
|
||||
// distinguish between core rules and plugin rules
|
||||
if (ruleId.includes("/")) {
|
||||
// mimic scoped npm packages
|
||||
if (ruleId.startsWith("@")) {
|
||||
pluginName = ruleId.slice(0, ruleId.lastIndexOf("/"));
|
||||
} else {
|
||||
pluginName = ruleId.slice(0, ruleId.indexOf("/"));
|
||||
}
|
||||
|
||||
ruleName = ruleId.slice(pluginName.length + 1);
|
||||
} else {
|
||||
pluginName = "@";
|
||||
ruleName = ruleId;
|
||||
}
|
||||
|
||||
return {
|
||||
pluginName,
|
||||
ruleName,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a rule instance from a given config based on the ruleId.
|
||||
* @param {string} ruleId The rule ID to look for.
|
||||
* @param {Linter.Config} config The config to search.
|
||||
* @returns {RuleDefinition|undefined} The rule if found
|
||||
* or undefined if not.
|
||||
*/
|
||||
function getRuleFromConfig(ruleId, config) {
|
||||
const { pluginName, ruleName } = parseRuleId(ruleId);
|
||||
|
||||
return config.plugins?.[pluginName]?.rules?.[ruleName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a complete options schema for a rule.
|
||||
* @param {RuleDefinition} rule A rule object
|
||||
* @throws {TypeError} If `meta.schema` is specified but is not an array, object or `false`.
|
||||
* @returns {Object|null} JSON Schema for the rule's options. `null` if `meta.schema` is `false`.
|
||||
*/
|
||||
function getRuleOptionsSchema(rule) {
|
||||
if (!rule.meta) {
|
||||
return { ...noOptionsSchema }; // default if `meta.schema` is not specified
|
||||
}
|
||||
|
||||
const schema = rule.meta.schema;
|
||||
|
||||
if (typeof schema === "undefined") {
|
||||
return { ...noOptionsSchema }; // default if `meta.schema` is not specified
|
||||
}
|
||||
|
||||
// `schema:false` is an allowed explicit opt-out of options validation for the rule
|
||||
if (schema === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof schema !== "object" || schema === null) {
|
||||
throw new TypeError("Rule's `meta.schema` must be an array or object");
|
||||
}
|
||||
|
||||
// ESLint-specific array form needs to be converted into a valid JSON Schema definition
|
||||
if (Array.isArray(schema)) {
|
||||
if (schema.length) {
|
||||
return {
|
||||
type: "array",
|
||||
items: schema,
|
||||
minItems: 0,
|
||||
maxItems: schema.length,
|
||||
};
|
||||
}
|
||||
|
||||
// `schema:[]` is an explicit way to specify that the rule does not accept any options
|
||||
return { ...noOptionsSchema };
|
||||
}
|
||||
|
||||
// `schema:<object>` is assumed to be a valid JSON Schema definition
|
||||
return schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a plugin identifier in the form a/b/c into two parts: a/b and c.
|
||||
* @param {string} identifier The identifier to parse.
|
||||
* @returns {{objectName: string, pluginName: string}} The parts of the plugin
|
||||
* name.
|
||||
*/
|
||||
function splitPluginIdentifier(identifier) {
|
||||
const parts = identifier.split("/");
|
||||
|
||||
return {
|
||||
objectName: parts.pop(),
|
||||
pluginName: parts.join("/"),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a language name by replacing the built-in `@/` plugin prefix with `js/`.
|
||||
* @param {string} languageName The language name to normalize.
|
||||
* @returns {string} The normalized language name.
|
||||
*/
|
||||
function normalizeLanguageName(languageName) {
|
||||
return languageName.startsWith("@/")
|
||||
? `js/${languageName.slice(2)}`
|
||||
: languageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a rule's `meta.languages` supports the given language.
|
||||
* @param {Array<string>|undefined} ruleLangs The rule's `meta.languages` array.
|
||||
* @param {string} configLanguageName The normalized language name from the config (e.g., "js/js").
|
||||
* @param {Array<string>} validPluginNames The valid plugin name aliases for the config's plugin
|
||||
* (normalized plugin name plus its `meta.namespace` if defined).
|
||||
* @returns {boolean} `true` if the rule supports the language, `false` otherwise.
|
||||
*/
|
||||
function doesRuleSupportLanguage(
|
||||
ruleLangs,
|
||||
configLanguageName,
|
||||
validPluginNames,
|
||||
) {
|
||||
// If no languages specified, works with all languages (backward compatible)
|
||||
if (!ruleLangs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { objectName: configLangPart } =
|
||||
splitPluginIdentifier(configLanguageName);
|
||||
|
||||
for (const langEntry of ruleLangs) {
|
||||
// Skip non-string entries
|
||||
if (typeof langEntry !== "string") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// "*" matches any language
|
||||
if (langEntry === "*") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Direct match
|
||||
if (langEntry === configLanguageName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { pluginName: rulePluginPart, objectName: ruleLangPart } =
|
||||
splitPluginIdentifier(langEntry);
|
||||
|
||||
// "plugin/*" wildcard - matches any language from that plugin (by name or namespace)
|
||||
if (ruleLangPart === "*") {
|
||||
if (validPluginNames.includes(rulePluginPart)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Match by plugin name or namespace, with exact language part
|
||||
if (
|
||||
validPluginNames.includes(rulePluginPart) &&
|
||||
ruleLangPart === configLangPart
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of an object in the config by reading its `meta` key.
|
||||
* @param {Object} object The object to check.
|
||||
* @returns {string?} The name of the object if found or `null` if there
|
||||
* is no name.
|
||||
*/
|
||||
function getObjectId(object) {
|
||||
// first check old-style name
|
||||
let name = object.name;
|
||||
|
||||
if (!name) {
|
||||
if (!object.meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
name = object.meta.name;
|
||||
|
||||
if (!name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// now check for old-style version
|
||||
let version = object.version;
|
||||
|
||||
if (!version) {
|
||||
version = object.meta && object.meta.version;
|
||||
}
|
||||
|
||||
// if there's a version then append that
|
||||
if (version) {
|
||||
return `${name}@${version}`;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a value is not a function.
|
||||
* @param {any} value The value to check.
|
||||
* @param {string} key The key of the value in the object.
|
||||
* @param {string} objectKey The key of the object being checked.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is a function.
|
||||
*/
|
||||
function assertNotFunction(value, key, objectKey) {
|
||||
if (typeof value === "function") {
|
||||
const error = new TypeError(
|
||||
`Cannot serialize key "${key}" in "${objectKey}": Function values are not supported.`,
|
||||
);
|
||||
|
||||
error.messageTemplate = "config-serialize-function";
|
||||
error.messageData = { key, objectKey };
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a languageOptions object to a JSON representation.
|
||||
* @param {Record<string, any>} languageOptions The options to create a JSON
|
||||
* representation of.
|
||||
* @param {string} objectKey The key of the object being converted.
|
||||
* @returns {Record<string, any>} The JSON representation of the languageOptions.
|
||||
* @throws {TypeError} If a function is found in the languageOptions.
|
||||
*/
|
||||
function languageOptionsToJSON(languageOptions, objectKey = "languageOptions") {
|
||||
if (typeof languageOptions.toJSON === "function") {
|
||||
const result = languageOptions.toJSON();
|
||||
|
||||
assertNotFunction(result, "toJSON", objectKey);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const result = {};
|
||||
|
||||
for (const [key, value] of Object.entries(languageOptions)) {
|
||||
if (value) {
|
||||
if (typeof value === "object") {
|
||||
const name = getObjectId(value);
|
||||
|
||||
if (typeof value.toJSON === "function") {
|
||||
result[key] = value.toJSON();
|
||||
assertNotFunction(result[key], key, objectKey);
|
||||
} else if (name && hasMethod(value)) {
|
||||
result[key] = name;
|
||||
} else {
|
||||
result[key] = languageOptionsToJSON(value, key);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
assertNotFunction(value, key, objectKey);
|
||||
}
|
||||
|
||||
result[key] = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates a validator for a rule.
|
||||
* @param {Object} rule The rule to get a validator for.
|
||||
* @param {string} ruleId The ID of the rule (for error reporting).
|
||||
* @returns {Function|null} A validation function or `null` if no validation is needed.
|
||||
* @throws {InvalidRuleOptionsSchemaError} If a rule's `meta.schema` is invalid.
|
||||
*/
|
||||
function getOrCreateValidator(rule, ruleId) {
|
||||
if (!validators.has(rule)) {
|
||||
try {
|
||||
const schema = getRuleOptionsSchema(rule);
|
||||
|
||||
if (schema) {
|
||||
validators.set(rule, ajv.compile(schema));
|
||||
}
|
||||
} catch (err) {
|
||||
throw new InvalidRuleOptionsSchemaError(ruleId, err);
|
||||
}
|
||||
}
|
||||
|
||||
return validators.get(rule);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Represents a normalized configuration object.
|
||||
*/
|
||||
class Config {
|
||||
/**
|
||||
* The name to use for the language when serializing to JSON.
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
#languageName;
|
||||
|
||||
/**
|
||||
* The name to use for the processor when serializing to JSON.
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
#processorName;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} config The configuration object.
|
||||
*/
|
||||
constructor(config) {
|
||||
const { plugins, language, languageOptions, processor, ...otherKeys } =
|
||||
config;
|
||||
|
||||
// Validate config object
|
||||
const schema = new ObjectSchema(flatConfigSchema);
|
||||
|
||||
schema.validate(config);
|
||||
|
||||
// first, copy all the other keys over
|
||||
Object.assign(this, otherKeys);
|
||||
|
||||
// ensure that a language is specified
|
||||
if (!language) {
|
||||
throw new TypeError("Key 'language' is required.");
|
||||
}
|
||||
|
||||
// copy the rest over
|
||||
this.plugins = plugins;
|
||||
this.language = language;
|
||||
|
||||
// Check language value
|
||||
const {
|
||||
pluginName: languagePluginName,
|
||||
objectName: localLanguageName,
|
||||
} = splitPluginIdentifier(language);
|
||||
|
||||
this.#languageName = language;
|
||||
|
||||
if (
|
||||
!plugins ||
|
||||
!plugins[languagePluginName] ||
|
||||
!plugins[languagePluginName].languages ||
|
||||
!plugins[languagePluginName].languages[localLanguageName]
|
||||
) {
|
||||
throw new TypeError(
|
||||
`Key "language": Could not find "${localLanguageName}" in plugin "${languagePluginName}".`,
|
||||
);
|
||||
}
|
||||
|
||||
this.language =
|
||||
plugins[languagePluginName].languages[localLanguageName];
|
||||
|
||||
if (this.language.defaultLanguageOptions ?? languageOptions) {
|
||||
this.languageOptions = flatConfigSchema.languageOptions.merge(
|
||||
this.language.defaultLanguageOptions,
|
||||
languageOptions,
|
||||
);
|
||||
} else {
|
||||
this.languageOptions = {};
|
||||
}
|
||||
|
||||
// Validate language options
|
||||
try {
|
||||
this.language.validateLanguageOptions(this.languageOptions);
|
||||
} catch (error) {
|
||||
throw new TypeError(`Key "languageOptions": ${error.message}`, {
|
||||
cause: error,
|
||||
});
|
||||
}
|
||||
|
||||
// Normalize language options if necessary
|
||||
if (this.language.normalizeLanguageOptions) {
|
||||
this.languageOptions = this.language.normalizeLanguageOptions(
|
||||
this.languageOptions,
|
||||
);
|
||||
}
|
||||
|
||||
// Check processor value
|
||||
if (processor) {
|
||||
this.processor = processor;
|
||||
|
||||
if (typeof processor === "string") {
|
||||
const { pluginName, objectName: localProcessorName } =
|
||||
splitPluginIdentifier(processor);
|
||||
|
||||
this.#processorName = processor;
|
||||
|
||||
if (
|
||||
!plugins ||
|
||||
!plugins[pluginName] ||
|
||||
!plugins[pluginName].processors ||
|
||||
!plugins[pluginName].processors[localProcessorName]
|
||||
) {
|
||||
throw new TypeError(
|
||||
`Key "processor": Could not find "${localProcessorName}" in plugin "${pluginName}".`,
|
||||
);
|
||||
}
|
||||
|
||||
this.processor =
|
||||
plugins[pluginName].processors[localProcessorName];
|
||||
} else if (typeof processor === "object") {
|
||||
this.#processorName = getObjectId(processor);
|
||||
this.processor = processor;
|
||||
} else {
|
||||
throw new TypeError(
|
||||
"Key 'processor' must be a string or an object.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Process the rules
|
||||
if (this.rules) {
|
||||
this.#normalizeRulesConfig();
|
||||
this.validateRulesConfig(this.rules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the configuration to a JSON representation.
|
||||
* @returns {Record<string, any>} The JSON representation of the configuration.
|
||||
* @throws {Error} If the configuration cannot be serialized.
|
||||
*/
|
||||
toJSON() {
|
||||
if (this.processor && !this.#processorName) {
|
||||
throw new Error(
|
||||
"Could not serialize processor object (missing 'meta' object).",
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.#languageName) {
|
||||
throw new Error(
|
||||
"Could not serialize language object (missing 'meta' object).",
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...this,
|
||||
plugins: Object.entries(this.plugins).map(([namespace, plugin]) => {
|
||||
const pluginId = getObjectId(plugin);
|
||||
|
||||
if (!pluginId) {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
return `${namespace}:${pluginId}`;
|
||||
}),
|
||||
language: this.#languageName,
|
||||
languageOptions: languageOptionsToJSON(this.languageOptions),
|
||||
processor: this.#processorName,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a rule configuration by its ID.
|
||||
* @param {string} ruleId The ID of the rule to get.
|
||||
* @returns {RuleDefinition|undefined} The rule definition from the plugin, or `undefined` if the rule is not found.
|
||||
*/
|
||||
getRuleDefinition(ruleId) {
|
||||
return getRuleFromConfig(ruleId, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the rules configuration. Ensures that each rule config is
|
||||
* an array and that the severity is a number. Applies meta.defaultOptions.
|
||||
* This function modifies `this.rules`.
|
||||
* @returns {void}
|
||||
*/
|
||||
#normalizeRulesConfig() {
|
||||
for (const [ruleId, originalConfig] of Object.entries(this.rules)) {
|
||||
// ensure rule config is an array
|
||||
let ruleConfig = Array.isArray(originalConfig)
|
||||
? originalConfig
|
||||
: [originalConfig];
|
||||
|
||||
// normalize severity
|
||||
ruleConfig[0] = severities.get(ruleConfig[0]);
|
||||
|
||||
const rule = getRuleFromConfig(ruleId, this);
|
||||
|
||||
// apply meta.defaultOptions
|
||||
const slicedOptions = ruleConfig.slice(1);
|
||||
const mergedOptions = deepMergeArrays(
|
||||
rule?.meta?.defaultOptions,
|
||||
slicedOptions,
|
||||
);
|
||||
|
||||
if (mergedOptions.length) {
|
||||
ruleConfig = [ruleConfig[0], ...mergedOptions];
|
||||
}
|
||||
|
||||
this.rules[ruleId] = ruleConfig;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates all of the rule configurations in the given rules config
|
||||
* against the plugins in this instance. This is used primarily to
|
||||
* validate inline configuration rules while inting.
|
||||
* @param {Object} rulesConfig The rules config to validate.
|
||||
* @returns {void}
|
||||
* @throws {Error} If a rule's configuration does not match its schema.
|
||||
* @throws {TypeError} If the rulesConfig is not provided or is invalid.
|
||||
* @throws {InvalidRuleOptionsSchemaError} If a rule's `meta.schema` is invalid.
|
||||
* @throws {TypeError} If a rule is not found in the plugins.
|
||||
* @throws {TypeError} If a rule does not support the current language.
|
||||
*/
|
||||
validateRulesConfig(rulesConfig) {
|
||||
if (!rulesConfig) {
|
||||
throw new TypeError("Config is required for validation.");
|
||||
}
|
||||
|
||||
// Normalize "@/" prefix to "js/" for matching and user-facing messages
|
||||
const normalizedLanguageName = normalizeLanguageName(
|
||||
this.#languageName,
|
||||
);
|
||||
|
||||
// Compute valid plugin name aliases for the config's language plugin once
|
||||
const { pluginName: configPluginName } = splitPluginIdentifier(
|
||||
normalizedLanguageName,
|
||||
);
|
||||
const configPlugin =
|
||||
this.plugins[configPluginName] ??
|
||||
(configPluginName === "js" ? this.plugins["@"] : void 0);
|
||||
const validPluginNames = configPlugin?.meta?.namespace
|
||||
? [configPluginName, configPlugin.meta.namespace]
|
||||
: [configPluginName];
|
||||
const unsupportedLanguageRules = [];
|
||||
|
||||
for (const [ruleId, ruleOptions] of Object.entries(rulesConfig)) {
|
||||
// check for edge case
|
||||
if (ruleId === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a rule is disabled, we don't do any validation. This allows
|
||||
* users to safely set any value to 0 or "off" without worrying
|
||||
* that it will cause a validation error.
|
||||
*
|
||||
* Note: ruleOptions is always an array at this point because
|
||||
* this validation occurs after FlatConfigArray has merged and
|
||||
* normalized values.
|
||||
*/
|
||||
if (ruleOptions[0] === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const rule = getRuleFromConfig(ruleId, this);
|
||||
|
||||
if (!rule) {
|
||||
throwRuleNotFoundError(parseRuleId(ruleId), this);
|
||||
}
|
||||
|
||||
// Validate meta.languages structure if present (only for enabled rules)
|
||||
if (rule.meta?.languages !== void 0) {
|
||||
if (!Array.isArray(rule.meta.languages)) {
|
||||
throw new TypeError(
|
||||
`Key "rules": Key "${ruleId}": Key "meta": Key "languages": Expected an array.`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const lang of rule.meta.languages) {
|
||||
if (typeof lang !== "string") {
|
||||
throw new TypeError(
|
||||
`Key "rules": Key "${ruleId}": Key "meta": Key "languages": Expected each element to be a string.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the rule supports the current language
|
||||
if (
|
||||
!doesRuleSupportLanguage(
|
||||
rule.meta?.languages,
|
||||
normalizedLanguageName,
|
||||
validPluginNames,
|
||||
)
|
||||
) {
|
||||
unsupportedLanguageRules.push(ruleId);
|
||||
}
|
||||
|
||||
const validateRule = getOrCreateValidator(rule, ruleId);
|
||||
|
||||
if (validateRule) {
|
||||
validateRule(ruleOptions.slice(1));
|
||||
|
||||
if (validateRule.errors) {
|
||||
throw new Error(
|
||||
`Key "rules": Key "${ruleId}":\n${validateRule.errors
|
||||
.map(error => {
|
||||
if (
|
||||
error.keyword === "additionalProperties" &&
|
||||
error.schema === false &&
|
||||
typeof error.parentSchema?.properties ===
|
||||
"object" &&
|
||||
typeof error.params?.additionalProperty ===
|
||||
"string"
|
||||
) {
|
||||
const expectedProperties = Object.keys(
|
||||
error.parentSchema.properties,
|
||||
).map(property => `"${property}"`);
|
||||
|
||||
return `\tValue ${JSON.stringify(error.data)} ${error.message}.\n\t\tUnexpected property "${error.params.additionalProperty}". Expected properties: ${expectedProperties.join(", ")}.\n`;
|
||||
}
|
||||
|
||||
return `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`;
|
||||
})
|
||||
.join("")}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unsupportedLanguageRules.length > 0) {
|
||||
const error = new TypeError(
|
||||
`Key "rules": The following rules do not support the language "${normalizedLanguageName}":\n${unsupportedLanguageRules.map(ruleId => `\t- "${ruleId}"`).join("\n")}`,
|
||||
);
|
||||
|
||||
error.messageTemplate = "rule-unsupported-language";
|
||||
error.messageData = {
|
||||
ruleIds: unsupportedLanguageRules,
|
||||
language: normalizedLanguageName,
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a complete options schema for a rule.
|
||||
* @param {RuleDefinition} ruleDefinition A rule definition object.
|
||||
* @throws {TypeError} If `meta.schema` is specified but is not an array, object or `false`.
|
||||
* @returns {Object|null} JSON Schema for the rule's options. `null` if `meta.schema` is `false`.
|
||||
*/
|
||||
static getRuleOptionsSchema(ruleDefinition) {
|
||||
return getRuleOptionsSchema(ruleDefinition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the severity value of a rule's configuration to a number
|
||||
* @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally
|
||||
* received from the user. A valid config value is either 0, 1, 2, the string "off" (treated the same as 0),
|
||||
* the string "warn" (treated the same as 1), the string "error" (treated the same as 2), or an array
|
||||
* whose first element is one of the above values. Strings are matched case-insensitively.
|
||||
* @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.
|
||||
*/
|
||||
static getRuleNumericSeverity(ruleConfig) {
|
||||
const severityValue = Array.isArray(ruleConfig)
|
||||
? ruleConfig[0]
|
||||
: ruleConfig;
|
||||
|
||||
if (severities.has(severityValue)) {
|
||||
return severities.get(severityValue);
|
||||
}
|
||||
|
||||
if (typeof severityValue === "string") {
|
||||
return severities.get(severityValue.toLowerCase()) ?? 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Config };
|
||||
Reference in New Issue
Block a user