WIP: bootstrap and partial real Solana watcher implementation

This commit is contained in:
2026-08-16 09:17:45 +00:00
commit dc23412c3f
7232 changed files with 1687637 additions and 0 deletions

View File

@@ -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;

View File

@@ -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"
]
}
}

View File

@@ -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
}
}

View File

@@ -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};

View File

@@ -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]],
};

View File

@@ -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'
>

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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"));

View File

@@ -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" });
});

View File

@@ -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};

View File

@@ -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();
};

View File

@@ -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"
}
}

View File

@@ -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

View File

@@ -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;
},
};

View File

@@ -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"
}
}

View File

@@ -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",
);
},
});
}
},
};
},
};

View File

@@ -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 };