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,82 @@
import { _ as _inherits } from "./_inherits.js";
import { _ as _set_prototype_of } from "./_set_prototype_of.js";
function _wrap_reg_exp(re, groups, source) {
_wrap_reg_exp = function(re, groups, source) {
return new WrappedRegExp(re, undefined, groups, source);
};
var _super = RegExp.prototype;
var _groups = new WeakMap();
var _sources = new WeakMap();
var _native_source = Object.getOwnPropertyDescriptor(_super, "source").get;
function WrappedRegExp(re, flags, groups, source) {
var _re = new RegExp(re, flags);
_groups.set(_re, groups || _groups.get(re));
_sources.set(_re, source !== undefined ? source : _sources.get(re));
return _set_prototype_of(_re, WrappedRegExp.prototype);
}
_inherits(WrappedRegExp, RegExp);
Object.defineProperty(WrappedRegExp.prototype, "source", {
configurable: true,
get: function() {
var source = _sources.get(this);
if (source !== undefined) {
try {
new RegExp(source, this.flags);
return source;
} catch (_) {}
}
return _native_source.call(this);
}
});
WrappedRegExp.prototype.exec = function(str) {
var result = _super.exec.call(this, str);
if (result) {
result.groups = buildGroups(result, this);
var indices = result.indices;
if (indices) indices.groups = buildGroups(indices, this);
}
return result;
};
WrappedRegExp.prototype[Symbol.replace] = function(str, substitution) {
if (typeof substitution === "string") {
var groups = _groups.get(this);
return _super[Symbol.replace].call(
this,
str,
substitution.replace(/\$<([^>]+)>/g, function(_, name) {
var group = groups ? groups[name] : undefined;
if (group === undefined) return "";
return "$" + (Array.isArray(group) ? group.join("$") : group);
})
);
}
if (typeof substitution === "function") {
var _this = this;
return _super[Symbol.replace].call(this, str, function() {
var args = arguments;
if (typeof args[args.length - 1] !== "object") {
args = [].slice.call(args);
args.push(buildGroups(args, _this));
}
return substitution.apply(this, args);
});
}
return _super[Symbol.replace].call(this, str, substitution);
};
function buildGroups(result, re) {
var g = _groups.get(re);
return Object.keys(g).reduce(function(groups, name) {
var i = g[name];
if (typeof i === "number") groups[name] = result[i];
else {
var k = 0;
while (result[i[k]] === undefined && k + 1 < i.length) k++;
groups[name] = result[i[k]];
}
return groups;
}, Object.create(null));
}
return _wrap_reg_exp.apply(this, arguments);
}
export { _wrap_reg_exp as _ };

View File

@@ -0,0 +1,195 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
interface Colors {
comment: {
close: string;
open: string;
};
content: {
close: string;
open: string;
};
prop: {
close: string;
open: string;
};
tag: {
close: string;
open: string;
};
value: {
close: string;
open: string;
};
}
type Indent = (arg0: string) => string;
type Refs = Array<unknown>;
type Print = (arg0: unknown) => string;
type Theme = Required<{
comment?: string;
content?: string;
prop?: string;
tag?: string;
value?: string;
}>;
/**
* compare function used when sorting object keys, `null` can be used to skip over sorting.
*/
type CompareKeys = ((a: string, b: string) => number) | null | undefined;
type RequiredOptions = Required<PrettyFormatOptions>;
interface Options extends Omit<RequiredOptions, "compareKeys" | "theme"> {
compareKeys: CompareKeys;
theme: Theme;
}
interface PrettyFormatOptions {
/**
* Call `toJSON` on objects before formatting them.
* Ignored after the formatter has already called `toJSON` once for a value.
* @default true
*/
callToJSON?: boolean;
/**
* Whether to escape special characters in regular expressions.
* @default false
*/
escapeRegex?: boolean;
/**
* Whether to escape special characters in strings.
* @default true
*/
escapeString?: boolean;
/**
* Whether to highlight syntax using terminal colors.
* @default false
*/
highlight?: boolean;
/**
* Number of spaces to use for each level of indentation.
* @default 2
*/
indent?: number;
/**
* Maximum depth to recurse into nested values.
* @default Infinity
*/
maxDepth?: number;
/**
* Maximum number of items to print in arrays, sets, maps, and similar collections.
* @default Infinity
*/
maxWidth?: number;
/**
* Approximate per-depth-level budget for output length.
* When the accumulated output at any single depth level exceeds this value,
* further nesting is collapsed. This is a heuristic safety valve, not a hard
* limit — total output can reach up to roughly `maxDepth × maxOutputLength`.
* @default 1_000_000
*/
maxOutputLength?: number;
/**
* Whether to minimize added whitespace, including indentation and line breaks.
* @default false
*/
min?: boolean;
/**
* Whether to print `Object` / `Array` prefixes for plain objects and arrays.
* @default true
*/
printBasicPrototype?: boolean;
/**
* Whether to include the function name when formatting functions.
* @default true
*/
printFunctionName?: boolean;
/**
* Whether to include shadow-root contents when formatting DOM nodes.
* @default true
*/
printShadowRoot?: boolean;
/**
* Compare function used when sorting object keys. Set to `null` to disable sorting.
*/
compareKeys?: CompareKeys;
/**
* Plugins used to serialize application-specific data types.
* @default []
*/
plugins?: Plugins;
}
type OptionsReceived = PrettyFormatOptions;
interface Config {
callToJSON: boolean;
compareKeys: CompareKeys;
colors: Colors;
escapeRegex: boolean;
escapeString: boolean;
indent: string;
maxDepth: number;
maxWidth: number;
min: boolean;
plugins: Plugins;
printBasicPrototype: boolean;
printFunctionName: boolean;
printShadowRoot: boolean;
spacingInner: string;
spacingOuter: string;
maxOutputLength: number;
}
type Printer = (val: unknown, config: Config, indentation: string, depth: number, refs: Refs, hasCalledToJSON?: boolean) => string;
type Test = (arg0: any) => boolean;
interface NewPlugin {
serialize: (val: any, config: Config, indentation: string, depth: number, refs: Refs, printer: Printer) => string;
test: Test;
}
interface PluginOptions {
edgeSpacing: string;
min: boolean;
spacing: string;
}
interface OldPlugin {
print: (val: unknown, print: Print, indent: Indent, options: PluginOptions, colors: Colors) => string;
test: Test;
}
type Plugin = NewPlugin | OldPlugin;
type Plugins = Array<Plugin>;
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
declare function createDOMElementFilter(filterNode?: (node: any) => boolean): NewPlugin;
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
declare const DEFAULT_OPTIONS: Options;
/**
* Returns a presentation string of your `val` object
* @param val any potential JavaScript object
* @param options Custom settings
*/
declare function format(val: unknown, options?: OptionsReceived): string;
declare const plugins: {
AsymmetricMatcher: NewPlugin;
DOMCollection: NewPlugin;
DOMElement: NewPlugin;
Immutable: NewPlugin;
ReactElement: NewPlugin;
ReactTestComponent: NewPlugin;
Error: NewPlugin;
};
export { DEFAULT_OPTIONS, createDOMElementFilter, format, plugins };
export type { Colors, CompareKeys, Config, NewPlugin, OldPlugin, Options, OptionsReceived, Plugin, Plugins, PrettyFormatOptions, Printer, Refs, Theme };

View File

@@ -0,0 +1,32 @@
/**
* Normalises alias mappings, ensuring that more specific aliases are resolved before less specific ones.
* This function also ensures that aliases do not resolve to themselves cyclically.
*
* @param _aliases - A set of alias mappings where each key is an alias and its value is the actual path it points to.
* @returns a set of normalised alias mappings.
*/
declare function normalizeAliases(_aliases: Record<string, string>): Record<string, string>;
/**
* Resolves a path string to its alias if applicable, otherwise returns the original path.
* This function normalises the path, resolves the alias and then joins it to the alias target if necessary.
*
* @param path - The path string to resolve.
* @param aliases - A set of alias mappings to use for resolution.
* @returns the resolved path as a string.
*/
declare function resolveAlias(path: string, aliases: Record<string, string>): string;
/**
* Resolves a path string to its possible alias.
*
* Returns an array of possible alias resolutions (could be empty), sorted by specificity (longest first).
*/
declare function reverseResolveAlias(path: string, aliases: Record<string, string>): string[];
/**
* Extracts the filename from a given path, excluding any directory paths and the file extension.
*
* @param path - The full path of the file from which to extract the filename.
* @returns the filename without the extension, or `undefined` if the filename cannot be extracted.
*/
declare function filename(path: string): string | undefined;
export { filename, normalizeAliases, resolveAlias, reverseResolveAlias };

View File

@@ -0,0 +1,23 @@
export {};
import * as buffer from "node:buffer";
type _Blob = typeof globalThis extends { onmessage: any } ? {} : buffer.Blob;
type _BlobPropertyBag = typeof globalThis extends { onmessage: any } ? {} : buffer.BlobPropertyBag;
type _File = typeof globalThis extends { onmessage: any } ? {} : buffer.File;
type _FilePropertyBag = typeof globalThis extends { onmessage: any } ? {} : buffer.FilePropertyBag;
declare global {
interface Blob extends _Blob {}
var Blob: typeof globalThis extends { onmessage: any; Blob: infer T } ? T : typeof buffer.Blob;
interface BlobPropertyBag extends _BlobPropertyBag {}
interface File extends _File {}
var File: typeof globalThis extends { onmessage: any; File: infer T } ? T : typeof buffer.File;
interface FilePropertyBag extends _FilePropertyBag {}
function atob(data: string): string;
function btoa(data: string): string;
}

View File

@@ -0,0 +1,41 @@
export * as core from "../core/index.js";
export * from "./parse.js";
export * from "./schemas.js";
export * from "./checks.js";
export type { infer, output, input } from "../core/index.js";
export type { JSONType } from "../core/util.js";
export {
globalRegistry,
registry,
config,
$output,
$input,
$brand,
clone,
regexes,
treeifyError,
prettifyError,
formatError,
flattenError,
TimePrecision,
util,
NEVER,
} from "../core/index.js";
export { toJSONSchema } from "../core/json-schema-processors.js";
export * as locales from "../locales/index.js";
/** A special constant with type `never` */
// export const NEVER = {} as never;
// iso
export * as iso from "./iso.js";
export {
ZodMiniISODateTime,
ZodMiniISODate,
ZodMiniISOTime,
ZodMiniISODuration,
} from "./iso.js";
// coerce
export * as coerce from "./coerce.js";

View File

@@ -0,0 +1,45 @@
'use strict'
const { test } = require('node:test')
const assert = require('node:assert')
const config = require('./pkg.config.json')
const { promisify } = require('util')
const { unlink } = require('fs/promises')
const { join } = require('path')
const { platform } = require('process')
const exec = promisify(require('child_process').exec)
test('worker test when packaged into executable using pkg', async () => {
const packageName = 'index'
// package the app into several node versions, check config for more info
const filePath = `${join(__dirname, packageName)}.js`
const configPath = join(__dirname, 'pkg.config.json')
process.env.NODE_OPTIONS ||= ''
process.env.NODE_OPTIONS = '--no-warnings'
const { stderr } = await exec(`npx pkg ${filePath} --config ${configPath}`)
// there should be no error when packaging
assert.strictEqual(stderr, '')
// pkg outputs files in the following format by default: {filename}-{node version}
for (const target of config.pkg.targets) {
// execute the packaged test
let executablePath = `${join(config.pkg.outputPath, packageName)}-${target}`
// when on windows, we need the .exe extension
if (platform === 'win32') {
executablePath = `${executablePath}.exe`
} else {
executablePath = `./${executablePath}`
}
const { stderr } = await exec(executablePath)
// check if there were no errors
assert.strictEqual(stderr, '')
// clean up afterwards
await unlink(executablePath)
}
})

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearProgramCache = void 0;
exports.clearCaches = clearCaches;
const getWatchProgramsForProjects_1 = require("./create-program/getWatchProgramsForProjects");
const parser_1 = require("./parser");
const candidateTSConfigRootDirs_1 = require("./parseSettings/candidateTSConfigRootDirs");
const createParseSettings_1 = require("./parseSettings/createParseSettings");
const resolveProjectList_1 = require("./parseSettings/resolveProjectList");
/**
* Clears all of the internal caches.
* Generally you shouldn't need or want to use this.
* Examples of intended uses:
* - In tests to reset parser state to keep tests isolated.
* - In custom lint tooling that iteratively lints one project at a time to prevent OOMs.
*/
function clearCaches() {
(0, candidateTSConfigRootDirs_1.clearCandidateTSConfigRootDirs)();
(0, parser_1.clearDefaultProjectMatchedFiles)();
(0, parser_1.clearProgramCache)();
(0, getWatchProgramsForProjects_1.clearWatchCaches)();
(0, createParseSettings_1.clearTSConfigMatchCache)();
(0, createParseSettings_1.clearTSServerProjectService)();
(0, resolveProjectList_1.clearGlobCache)();
}
// TODO - delete this in next major
exports.clearProgramCache = clearCaches;

View File

@@ -0,0 +1,21 @@
var cp = require('child_process');
/**
* Returns the version string of the current working directory.
* It is the git short hash of the last commit that changed filePath
* If there are uncommitted changes to this filePath, this method will throw.
* @returns {string}
*/
module.exports = function getGitHashSync(filePath) {
var commandResult;
try {
cp.execSync('git diff-index --quiet HEAD -- ' + filePath, { encoding: 'utf-8' });
} catch (err) {
//throw new Error('Cannot resolve git hash of file ' + filePath + ': There are uncommitted changes to file ' + filePath);
}
commandResult = cp.execSync('git log -n1 --pretty=format:%h -- ' + filePath, { encoding: 'utf-8' });
if (!commandResult) {
throw new Error("Could not get hash: file " + filePath + " does not exist");
}
return commandResult;
};

View File

@@ -0,0 +1,23 @@
'use strict'
const { test } = require('node:test')
const assert = require('node:assert')
const { join } = require('path')
const { once } = require('events')
const { MessageChannel } = require('worker_threads')
const ThreadStream = require('..')
test('message events emitted on the stream are posted to the worker', async function (t) {
const { port1, port2 } = new MessageChannel()
const stream = new ThreadStream({
filename: join(__dirname, 'on-message.js'),
sync: false
})
t.after(() => {
stream.end()
})
stream.emit('message', { text: 'hello', takeThisPortPlease: port1 }, [port1])
const [confirmation] = await once(port2, 'message')
assert.strictEqual(confirmation, 'received: hello')
})

View File

@@ -0,0 +1,6 @@
import type { ParserServicesWithTypeInformation, TSESTree } from '@typescript-eslint/utils';
import type { ReportDescriptor, RuleContext } from '@typescript-eslint/utils/ts-eslint';
import type { PreferOptionalChainMessageIds, PreferOptionalChainOptions } from './PreferOptionalChainOptions';
export declare function checkNullishAndReport(context: RuleContext<PreferOptionalChainMessageIds, [
PreferOptionalChainOptions
]>, parserServices: ParserServicesWithTypeInformation, { requireNullish }: PreferOptionalChainOptions, maybeNullishNodes: TSESTree.Expression[], descriptor: ReportDescriptor<PreferOptionalChainMessageIds>): void;

View File

@@ -0,0 +1,747 @@
const { humanReadableArgName } = require('./argument.js');
/**
* TypeScript import types for JSDoc, used by Visual Studio Code IntelliSense and `npm run typescript-checkJS`
* https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#import-types
* @typedef { import("./argument.js").Argument } Argument
* @typedef { import("./command.js").Command } Command
* @typedef { import("./option.js").Option } Option
*/
// Although this is a class, methods are static in style to allow override using subclass or just functions.
class Help {
constructor() {
this.helpWidth = undefined;
this.minWidthToWrap = 40;
this.sortSubcommands = false;
this.sortOptions = false;
this.showGlobalOptions = false;
}
/**
* prepareContext is called by Commander after applying overrides from `Command.configureHelp()`
* and just before calling `formatHelp()`.
*
* Commander just uses the helpWidth and the rest is provided for optional use by more complex subclasses.
*
* @param {{ error?: boolean, helpWidth?: number, outputHasColors?: boolean }} contextOptions
*/
prepareContext(contextOptions) {
this.helpWidth = this.helpWidth ?? contextOptions.helpWidth ?? 80;
}
/**
* Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one.
*
* @param {Command} cmd
* @returns {Command[]}
*/
visibleCommands(cmd) {
const visibleCommands = cmd.commands.filter((cmd) => !cmd._hidden);
const helpCommand = cmd._getHelpCommand();
if (helpCommand && !helpCommand._hidden) {
visibleCommands.push(helpCommand);
}
if (this.sortSubcommands) {
visibleCommands.sort((a, b) => {
// @ts-ignore: because overloaded return type
return a.name().localeCompare(b.name());
});
}
return visibleCommands;
}
/**
* Compare options for sort.
*
* @param {Option} a
* @param {Option} b
* @returns {number}
*/
compareOptions(a, b) {
const getSortKey = (option) => {
// WYSIWYG for order displayed in help. Short used for comparison if present. No special handling for negated.
return option.short
? option.short.replace(/^-/, '')
: option.long.replace(/^--/, '');
};
return getSortKey(a).localeCompare(getSortKey(b));
}
/**
* Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one.
*
* @param {Command} cmd
* @returns {Option[]}
*/
visibleOptions(cmd) {
const visibleOptions = cmd.options.filter((option) => !option.hidden);
// Built-in help option.
const helpOption = cmd._getHelpOption();
if (helpOption && !helpOption.hidden) {
// Automatically hide conflicting flags. Bit dubious but a historical behaviour that is convenient for single-command programs.
const removeShort = helpOption.short && cmd._findOption(helpOption.short);
const removeLong = helpOption.long && cmd._findOption(helpOption.long);
if (!removeShort && !removeLong) {
visibleOptions.push(helpOption); // no changes needed
} else if (helpOption.long && !removeLong) {
visibleOptions.push(
cmd.createOption(helpOption.long, helpOption.description),
);
} else if (helpOption.short && !removeShort) {
visibleOptions.push(
cmd.createOption(helpOption.short, helpOption.description),
);
}
}
if (this.sortOptions) {
visibleOptions.sort(this.compareOptions);
}
return visibleOptions;
}
/**
* Get an array of the visible global options. (Not including help.)
*
* @param {Command} cmd
* @returns {Option[]}
*/
visibleGlobalOptions(cmd) {
if (!this.showGlobalOptions) return [];
const globalOptions = [];
for (
let ancestorCmd = cmd.parent;
ancestorCmd;
ancestorCmd = ancestorCmd.parent
) {
const visibleOptions = ancestorCmd.options.filter(
(option) => !option.hidden,
);
globalOptions.push(...visibleOptions);
}
if (this.sortOptions) {
globalOptions.sort(this.compareOptions);
}
return globalOptions;
}
/**
* Get an array of the arguments if any have a description.
*
* @param {Command} cmd
* @returns {Argument[]}
*/
visibleArguments(cmd) {
// Side effect! Apply the legacy descriptions before the arguments are displayed.
if (cmd._argsDescription) {
cmd.registeredArguments.forEach((argument) => {
argument.description =
argument.description || cmd._argsDescription[argument.name()] || '';
});
}
// If there are any arguments with a description then return all the arguments.
if (cmd.registeredArguments.find((argument) => argument.description)) {
return cmd.registeredArguments;
}
return [];
}
/**
* Get the command term to show in the list of subcommands.
*
* @param {Command} cmd
* @returns {string}
*/
subcommandTerm(cmd) {
// Legacy. Ignores custom usage string, and nested commands.
const args = cmd.registeredArguments
.map((arg) => humanReadableArgName(arg))
.join(' ');
return (
cmd._name +
(cmd._aliases[0] ? '|' + cmd._aliases[0] : '') +
(cmd.options.length ? ' [options]' : '') + // simplistic check for non-help option
(args ? ' ' + args : '')
);
}
/**
* Get the option term to show in the list of options.
*
* @param {Option} option
* @returns {string}
*/
optionTerm(option) {
return option.flags;
}
/**
* Get the argument term to show in the list of arguments.
*
* @param {Argument} argument
* @returns {string}
*/
argumentTerm(argument) {
return argument.name();
}
/**
* Get the longest command term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
longestSubcommandTermLength(cmd, helper) {
return helper.visibleCommands(cmd).reduce((max, command) => {
return Math.max(
max,
this.displayWidth(
helper.styleSubcommandTerm(helper.subcommandTerm(command)),
),
);
}, 0);
}
/**
* Get the longest option term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
longestOptionTermLength(cmd, helper) {
return helper.visibleOptions(cmd).reduce((max, option) => {
return Math.max(
max,
this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),
);
}, 0);
}
/**
* Get the longest global option term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
longestGlobalOptionTermLength(cmd, helper) {
return helper.visibleGlobalOptions(cmd).reduce((max, option) => {
return Math.max(
max,
this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),
);
}, 0);
}
/**
* Get the longest argument term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
longestArgumentTermLength(cmd, helper) {
return helper.visibleArguments(cmd).reduce((max, argument) => {
return Math.max(
max,
this.displayWidth(
helper.styleArgumentTerm(helper.argumentTerm(argument)),
),
);
}, 0);
}
/**
* Get the command usage to be displayed at the top of the built-in help.
*
* @param {Command} cmd
* @returns {string}
*/
commandUsage(cmd) {
// Usage
let cmdName = cmd._name;
if (cmd._aliases[0]) {
cmdName = cmdName + '|' + cmd._aliases[0];
}
let ancestorCmdNames = '';
for (
let ancestorCmd = cmd.parent;
ancestorCmd;
ancestorCmd = ancestorCmd.parent
) {
ancestorCmdNames = ancestorCmd.name() + ' ' + ancestorCmdNames;
}
return ancestorCmdNames + cmdName + ' ' + cmd.usage();
}
/**
* Get the description for the command.
*
* @param {Command} cmd
* @returns {string}
*/
commandDescription(cmd) {
// @ts-ignore: because overloaded return type
return cmd.description();
}
/**
* Get the subcommand summary to show in the list of subcommands.
* (Fallback to description for backwards compatibility.)
*
* @param {Command} cmd
* @returns {string}
*/
subcommandDescription(cmd) {
// @ts-ignore: because overloaded return type
return cmd.summary() || cmd.description();
}
/**
* Get the option description to show in the list of options.
*
* @param {Option} option
* @return {string}
*/
optionDescription(option) {
const extraInfo = [];
if (option.argChoices) {
extraInfo.push(
// use stringify to match the display of the default value
`choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,
);
}
if (option.defaultValue !== undefined) {
// default for boolean and negated more for programmer than end user,
// but show true/false for boolean option as may be for hand-rolled env or config processing.
const showDefault =
option.required ||
option.optional ||
(option.isBoolean() && typeof option.defaultValue === 'boolean');
if (showDefault) {
extraInfo.push(
`default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`,
);
}
}
// preset for boolean and negated are more for programmer than end user
if (option.presetArg !== undefined && option.optional) {
extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);
}
if (option.envVar !== undefined) {
extraInfo.push(`env: ${option.envVar}`);
}
if (extraInfo.length > 0) {
const extraDescription = `(${extraInfo.join(', ')})`;
if (option.description) {
return `${option.description} ${extraDescription}`;
}
return extraDescription;
}
return option.description;
}
/**
* Get the argument description to show in the list of arguments.
*
* @param {Argument} argument
* @return {string}
*/
argumentDescription(argument) {
const extraInfo = [];
if (argument.argChoices) {
extraInfo.push(
// use stringify to match the display of the default value
`choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,
);
}
if (argument.defaultValue !== undefined) {
extraInfo.push(
`default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`,
);
}
if (extraInfo.length > 0) {
const extraDescription = `(${extraInfo.join(', ')})`;
if (argument.description) {
return `${argument.description} ${extraDescription}`;
}
return extraDescription;
}
return argument.description;
}
/**
* Format a list of items, given a heading and an array of formatted items.
*
* @param {string} heading
* @param {string[]} items
* @param {Help} helper
* @returns string[]
*/
formatItemList(heading, items, helper) {
if (items.length === 0) return [];
return [helper.styleTitle(heading), ...items, ''];
}
/**
* Group items by their help group heading.
*
* @param {Command[] | Option[]} unsortedItems
* @param {Command[] | Option[]} visibleItems
* @param {Function} getGroup
* @returns {Map<string, Command[] | Option[]>}
*/
groupItems(unsortedItems, visibleItems, getGroup) {
const result = new Map();
// Add groups in order of appearance in unsortedItems.
unsortedItems.forEach((item) => {
const group = getGroup(item);
if (!result.has(group)) result.set(group, []);
});
// Add items in order of appearance in visibleItems.
visibleItems.forEach((item) => {
const group = getGroup(item);
if (!result.has(group)) {
result.set(group, []);
}
result.get(group).push(item);
});
return result;
}
/**
* Generate the built-in help text.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {string}
*/
formatHelp(cmd, helper) {
const termWidth = helper.padWidth(cmd, helper);
const helpWidth = helper.helpWidth ?? 80; // in case prepareContext() was not called
function callFormatItem(term, description) {
return helper.formatItem(term, termWidth, description, helper);
}
// Usage
let output = [
`${helper.styleTitle('Usage:')} ${helper.styleUsage(helper.commandUsage(cmd))}`,
'',
];
// Description
const commandDescription = helper.commandDescription(cmd);
if (commandDescription.length > 0) {
output = output.concat([
helper.boxWrap(
helper.styleCommandDescription(commandDescription),
helpWidth,
),
'',
]);
}
// Arguments
const argumentList = helper.visibleArguments(cmd).map((argument) => {
return callFormatItem(
helper.styleArgumentTerm(helper.argumentTerm(argument)),
helper.styleArgumentDescription(helper.argumentDescription(argument)),
);
});
output = output.concat(
this.formatItemList('Arguments:', argumentList, helper),
);
// Options
const optionGroups = this.groupItems(
cmd.options,
helper.visibleOptions(cmd),
(option) => option.helpGroupHeading ?? 'Options:',
);
optionGroups.forEach((options, group) => {
const optionList = options.map((option) => {
return callFormatItem(
helper.styleOptionTerm(helper.optionTerm(option)),
helper.styleOptionDescription(helper.optionDescription(option)),
);
});
output = output.concat(this.formatItemList(group, optionList, helper));
});
if (helper.showGlobalOptions) {
const globalOptionList = helper
.visibleGlobalOptions(cmd)
.map((option) => {
return callFormatItem(
helper.styleOptionTerm(helper.optionTerm(option)),
helper.styleOptionDescription(helper.optionDescription(option)),
);
});
output = output.concat(
this.formatItemList('Global Options:', globalOptionList, helper),
);
}
// Commands
const commandGroups = this.groupItems(
cmd.commands,
helper.visibleCommands(cmd),
(sub) => sub.helpGroup() || 'Commands:',
);
commandGroups.forEach((commands, group) => {
const commandList = commands.map((sub) => {
return callFormatItem(
helper.styleSubcommandTerm(helper.subcommandTerm(sub)),
helper.styleSubcommandDescription(helper.subcommandDescription(sub)),
);
});
output = output.concat(this.formatItemList(group, commandList, helper));
});
return output.join('\n');
}
/**
* Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations.
*
* @param {string} str
* @returns {number}
*/
displayWidth(str) {
return stripColor(str).length;
}
/**
* Style the title for displaying in the help. Called with 'Usage:', 'Options:', etc.
*
* @param {string} str
* @returns {string}
*/
styleTitle(str) {
return str;
}
styleUsage(str) {
// Usage has lots of parts the user might like to color separately! Assume default usage string which is formed like:
// command subcommand [options] [command] <foo> [bar]
return str
.split(' ')
.map((word) => {
if (word === '[options]') return this.styleOptionText(word);
if (word === '[command]') return this.styleSubcommandText(word);
if (word[0] === '[' || word[0] === '<')
return this.styleArgumentText(word);
return this.styleCommandText(word); // Restrict to initial words?
})
.join(' ');
}
styleCommandDescription(str) {
return this.styleDescriptionText(str);
}
styleOptionDescription(str) {
return this.styleDescriptionText(str);
}
styleSubcommandDescription(str) {
return this.styleDescriptionText(str);
}
styleArgumentDescription(str) {
return this.styleDescriptionText(str);
}
styleDescriptionText(str) {
return str;
}
styleOptionTerm(str) {
return this.styleOptionText(str);
}
styleSubcommandTerm(str) {
// This is very like usage with lots of parts! Assume default string which is formed like:
// subcommand [options] <foo> [bar]
return str
.split(' ')
.map((word) => {
if (word === '[options]') return this.styleOptionText(word);
if (word[0] === '[' || word[0] === '<')
return this.styleArgumentText(word);
return this.styleSubcommandText(word); // Restrict to initial words?
})
.join(' ');
}
styleArgumentTerm(str) {
return this.styleArgumentText(str);
}
styleOptionText(str) {
return str;
}
styleArgumentText(str) {
return str;
}
styleSubcommandText(str) {
return str;
}
styleCommandText(str) {
return str;
}
/**
* Calculate the pad width from the maximum term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
padWidth(cmd, helper) {
return Math.max(
helper.longestOptionTermLength(cmd, helper),
helper.longestGlobalOptionTermLength(cmd, helper),
helper.longestSubcommandTermLength(cmd, helper),
helper.longestArgumentTermLength(cmd, helper),
);
}
/**
* Detect manually wrapped and indented strings by checking for line break followed by whitespace.
*
* @param {string} str
* @returns {boolean}
*/
preformatted(str) {
return /\n[^\S\r\n]/.test(str);
}
/**
* Format the "item", which consists of a term and description. Pad the term and wrap the description, indenting the following lines.
*
* So "TTT", 5, "DDD DDDD DD DDD" might be formatted for this.helpWidth=17 like so:
* TTT DDD DDDD
* DD DDD
*
* @param {string} term
* @param {number} termWidth
* @param {string} description
* @param {Help} helper
* @returns {string}
*/
formatItem(term, termWidth, description, helper) {
const itemIndent = 2;
const itemIndentStr = ' '.repeat(itemIndent);
if (!description) return itemIndentStr + term;
// Pad the term out to a consistent width, so descriptions are aligned.
const paddedTerm = term.padEnd(
termWidth + term.length - helper.displayWidth(term),
);
// Format the description.
const spacerWidth = 2; // between term and description
const helpWidth = this.helpWidth ?? 80; // in case prepareContext() was not called
const remainingWidth = helpWidth - termWidth - spacerWidth - itemIndent;
let formattedDescription;
if (
remainingWidth < this.minWidthToWrap ||
helper.preformatted(description)
) {
formattedDescription = description;
} else {
const wrappedDescription = helper.boxWrap(description, remainingWidth);
formattedDescription = wrappedDescription.replace(
/\n/g,
'\n' + ' '.repeat(termWidth + spacerWidth),
);
}
// Construct and overall indent.
return (
itemIndentStr +
paddedTerm +
' '.repeat(spacerWidth) +
formattedDescription.replace(/\n/g, `\n${itemIndentStr}`)
);
}
/**
* Wrap a string at whitespace, preserving existing line breaks.
* Wrapping is skipped if the width is less than `minWidthToWrap`.
*
* @param {string} str
* @param {number} width
* @returns {string}
*/
boxWrap(str, width) {
if (width < this.minWidthToWrap) return str;
const rawLines = str.split(/\r\n|\n/);
// split up text by whitespace
const chunkPattern = /[\s]*[^\s]+/g;
const wrappedLines = [];
rawLines.forEach((line) => {
const chunks = line.match(chunkPattern);
if (chunks === null) {
wrappedLines.push('');
return;
}
let sumChunks = [chunks.shift()];
let sumWidth = this.displayWidth(sumChunks[0]);
chunks.forEach((chunk) => {
const visibleWidth = this.displayWidth(chunk);
// Accumulate chunks while they fit into width.
if (sumWidth + visibleWidth <= width) {
sumChunks.push(chunk);
sumWidth += visibleWidth;
return;
}
wrappedLines.push(sumChunks.join(''));
const nextChunk = chunk.trimStart(); // trim space at line break
sumChunks = [nextChunk];
sumWidth = this.displayWidth(nextChunk);
});
wrappedLines.push(sumChunks.join(''));
});
return wrappedLines.join('\n');
}
}
/**
* Strip style ANSI escape sequences from the string. In particular, SGR (Select Graphic Rendition) codes.
*
* @param {string} str
* @returns {string}
* @package
*/
function stripColor(str) {
// eslint-disable-next-line no-control-regex
const sgrPattern = /\x1b\[\d*(;\d*)*m/g;
return str.replace(sgrPattern, '');
}
exports.Help = Help;
exports.stripColor = stripColor;

View File

@@ -0,0 +1,287 @@
import { SyntaxKind } from "../../ast/index.js";
import { getNodeCommonData, getNodeDataType, } from "./encoder.generated.js";
import { MsgpackWriter } from "./msgpack.js";
import { childProperties, HEADER_OFFSET_EXTENDED_DATA, HEADER_OFFSET_METADATA, HEADER_OFFSET_NODES, HEADER_OFFSET_STRING_TABLE, HEADER_OFFSET_STRING_TABLE_OFFSETS, HEADER_OFFSET_STRUCTURED_DATA, HEADER_SIZE, KIND_NODE_LIST, NODE_DATA_TYPE_CHILDREN, NODE_DATA_TYPE_EXTENDED, NODE_DATA_TYPE_STRING, NODE_LEN, PROTOCOL_VERSION, } from "./protocol.js";
const NODE_FIELDS = NODE_LEN / 4;
const NODE_FIELD_NEXT = 3;
const NO_STRUCTURED_DATA = 0xFFFFFFFF;
// String table that accumulates strings into a flat byte pool.
class StringTable {
parts;
byteLen;
offsets;
constructor() {
this.parts = [];
this.byteLen = 0;
this.offsets = [];
}
add(text) {
const index = this.offsets.length;
const encoder = cachedEncoder();
const encodedLength = encoder.encode(text).length;
const offset = this.byteLen;
this.parts.push(text);
this.byteLen += encodedLength;
this.offsets.push(offset, offset + encodedLength);
return index;
}
encode() {
const encoder = cachedEncoder();
const dataBytes = encoder.encode(this.parts.join(""));
const offsetBytes = new Uint8Array(this.offsets.length * 4);
const view = new DataView(offsetBytes.buffer);
for (let i = 0; i < this.offsets.length; i++) {
view.setUint32(i * 4, this.offsets[i], true);
}
const result = new Uint8Array(offsetBytes.length + dataBytes.length);
result.set(offsetBytes, 0);
result.set(dataBytes, offsetBytes.length);
return result;
}
stringByteLength() {
return this.byteLen;
}
offsetsCount() {
return this.offsets.length;
}
}
let _encoder;
function cachedEncoder() {
return _encoder ??= new TextEncoder();
}
function getChildrenPropertyMask(node) {
const kind = node.kind;
const props = childProperties[kind];
if (!props) {
return 0;
}
const n = node;
let mask = 0;
for (let i = 0; i < props.length; i++) {
const prop = props[i];
if (prop !== undefined && isChildPresent(n[prop])) {
mask |= 1 << i;
}
}
return mask;
}
// A child is "present" if it's non-null/non-undefined.
// This matches the Go encoder's behavior where non-nil NodeLists (even empty)
// are treated as present, and only nil NodeLists are absent.
function isChildPresent(v) {
if (v === undefined || v === null)
return false;
return true;
}
function recordNodeStrings(node, strs) {
return strs.add(node.text ?? "");
}
function encodeFileReferences(refs, writer) {
if (!refs || refs.length === 0)
return NO_STRUCTURED_DATA;
const offset = writer.finish().length;
writer.writeArrayHeader(refs.length);
for (const ref of refs) {
writer.writeArrayHeader(5);
writer.writeUint(ref.pos);
writer.writeUint(ref.end);
writer.writeString(ref.fileName);
writer.writeUint(ref.resolutionMode ?? 0);
writer.writeBool(ref.preserve ?? false);
}
return offset;
}
function recordExtendedData(node, strs, extendedData, structuredWriter) {
const offset = extendedData.length * 4;
if (node.kind === SyntaxKind.SourceFile) {
const sf = node;
const textIndex = strs.add(sf.text);
const fileNameIndex = strs.add(sf.fileName);
const pathIndex = strs.add(sf.path);
const referencedFilesOffset = encodeFileReferences(sf.referencedFiles, structuredWriter);
const typeRefDirectivesOffset = encodeFileReferences(sf.typeReferenceDirectives, structuredWriter);
const libRefDirectivesOffset = encodeFileReferences(sf.libReferenceDirectives, structuredWriter);
extendedData.push(textIndex, fileNameIndex, pathIndex, sf.languageVariant, sf.scriptKind, referencedFilesOffset, typeRefDirectivesOffset, libRefDirectivesOffset, NO_STRUCTURED_DATA, NO_STRUCTURED_DATA, NO_STRUCTURED_DATA, 0);
}
else if (node.kind === SyntaxKind.TemplateHead ||
node.kind === SyntaxKind.TemplateMiddle ||
node.kind === SyntaxKind.TemplateTail) {
const tmpl = node;
const text = tmpl.text ?? "";
const rawText = tmpl.rawText ?? "";
const templateFlags = tmpl.templateFlags ?? 0;
const textIndex = strs.add(text);
const rawTextIndex = strs.add(rawText);
extendedData.push(textIndex, rawTextIndex, templateFlags);
}
else {
// StringLiteral, NumericLiteral, BigIntLiteral, RegularExpressionLiteral,
// NoSubstitutionTemplateLiteral — format: [textIndex, tokenFlags]
const n = node;
const text = n.text ?? "";
const tokenFlags = n.tokenFlags ?? 0;
const textIndex = strs.add(text);
extendedData.push(textIndex, tokenFlags);
}
return offset;
}
function getNodeData(node, strs, extendedData, structuredWriter) {
const t = getNodeDataType(node.kind);
const common = getNodeCommonData(node);
switch (t) {
case NODE_DATA_TYPE_CHILDREN:
return t | common | getChildrenPropertyMask(node);
case NODE_DATA_TYPE_STRING:
return t | common | recordNodeStrings(node, strs);
case NODE_DATA_TYPE_EXTENDED:
return t | common | recordExtendedData(node, strs, extendedData, structuredWriter);
default:
throw new Error("unreachable");
}
}
function getChildPropertiesForNode(node) {
return childProperties[node.kind];
}
// Returns whether a value is a NodeArray (array-like with pos and end).
function isNodeArray(value) {
return Array.isArray(value) && typeof value.pos === "number" && typeof value.end === "number";
}
/**
* Encode a SourceFile AST node into the binary format.
*/
export function encodeSourceFile(sourceFile) {
return encodeNode(sourceFile);
}
/**
* Encode an arbitrary AST node into the binary format.
* When encoding a non-SourceFile node, the header hash and parse options fields will be zero.
*/
export function encodeNode(node) {
const strs = new StringTable();
const extendedDataValues = [];
const structuredWriter = new MsgpackWriter();
// We'll build an array of uint32 values for the nodes section, 7 per node
const nodeValues = [];
// Nil node (index 0)
nodeValues.push(0, 0, 0, 0, 0, 0, 0);
let nodeCount = 0;
let parentIndex = 0;
let prevIndex = 0;
function visitNode(node) {
nodeCount++;
const currentIndex = nodeCount;
if (prevIndex !== 0) {
// Set next pointer on previous sibling
nodeValues[prevIndex * NODE_FIELDS + NODE_FIELD_NEXT] = currentIndex;
}
const data = getNodeData(node, strs, extendedDataValues, structuredWriter);
nodeValues.push(node.kind, node.pos >= 0 ? node.pos : 0, node.end >= 0 ? node.end : 0, 0, // next (filled in later)
parentIndex, data, node.flags);
const saveParentIndex = parentIndex;
const savePrevIndex = prevIndex;
parentIndex = currentIndex;
prevIndex = 0;
visitChildren(node);
prevIndex = currentIndex;
parentIndex = saveParentIndex;
}
function visitNodeList(list) {
if (!list) {
return;
}
nodeCount++;
const currentIndex = nodeCount;
if (prevIndex !== 0) {
nodeValues[prevIndex * NODE_FIELDS + NODE_FIELD_NEXT] = currentIndex;
}
nodeValues.push(KIND_NODE_LIST, list.pos >= 0 ? list.pos : 0, list.end >= 0 ? list.end : 0, 0, // next
parentIndex, list.length, // data for NodeList is its length
0);
const saveParentIndex = parentIndex;
parentIndex = currentIndex;
prevIndex = 0;
for (const child of list) {
visitNode(child);
}
prevIndex = currentIndex;
parentIndex = saveParentIndex;
}
function visitChildren(node) {
const props = getChildPropertiesForNode(node);
const n = node;
if (props) {
for (const propName of props) {
if (propName === undefined)
continue;
const child = n[propName];
if (child === undefined || child === null)
continue;
if (isNodeArray(child)) {
visitNodeList(child);
}
else {
visitNode(child);
}
}
}
}
// Encode root node
nodeCount++;
parentIndex++;
const rootData = getNodeData(node, strs, extendedDataValues, structuredWriter);
nodeValues.push(node.kind, node.pos >= 0 ? node.pos : 0, node.end >= 0 ? node.end : 0, 0, 0, rootData, node.flags);
const saveParent = parentIndex;
prevIndex = 0;
parentIndex = 1; // root is at index 1
visitChildren(node);
parentIndex = saveParent;
// Encode extended data section
const extendedDataBytes = new Uint8Array(extendedDataValues.length * 4);
const extView = new DataView(extendedDataBytes.buffer);
for (let i = 0; i < extendedDataValues.length; i++) {
extView.setUint32(i * 4, extendedDataValues[i], true);
}
// Encode structured data section
const structuredDataBytes = structuredWriter.finish();
// Encode string table
const strsBytes = strs.encode();
// Encode nodes section
const nodesBytes = new Uint8Array(nodeValues.length * 4);
const nodesView = new DataView(nodesBytes.buffer);
for (let i = 0; i < nodeValues.length; i++) {
nodesView.setUint32(i * 4, nodeValues[i] >>> 0, true);
}
// Calculate section offsets
const offsetStringTableOffsets = HEADER_SIZE;
const offsetStringTableData = HEADER_SIZE + strs.offsetsCount() * 4;
const offsetExtendedData = offsetStringTableData + strs.stringByteLength();
const offsetStructuredData = offsetExtendedData + extendedDataBytes.length;
const offsetNodes = offsetStructuredData + structuredDataBytes.length;
// Build header
const header = new Uint8Array(HEADER_SIZE);
const headerView = new DataView(header.buffer);
const metadata = PROTOCOL_VERSION << 24;
headerView.setUint32(HEADER_OFFSET_METADATA, metadata, true);
// bytes 4-19: hash (zero for non-SourceFile, we don't have access to xxh3 here)
// byte 20-23: parse options (zero for non-SourceFile)
headerView.setUint32(HEADER_OFFSET_STRING_TABLE_OFFSETS, offsetStringTableOffsets, true);
headerView.setUint32(HEADER_OFFSET_STRING_TABLE, offsetStringTableData, true);
headerView.setUint32(HEADER_OFFSET_EXTENDED_DATA, offsetExtendedData, true);
headerView.setUint32(HEADER_OFFSET_STRUCTURED_DATA, offsetStructuredData, true);
headerView.setUint32(HEADER_OFFSET_NODES, offsetNodes, true);
// Concatenate all sections
const result = new Uint8Array(header.length + strsBytes.length + extendedDataBytes.length + structuredDataBytes.length + nodesBytes.length);
result.set(header, 0);
result.set(strsBytes, HEADER_SIZE);
result.set(extendedDataBytes, offsetExtendedData);
result.set(structuredDataBytes, offsetStructuredData);
result.set(nodesBytes, offsetNodes);
return result;
}
/**
* Encode a Uint8Array to a base64 string.
*/
export function uint8ArrayToBase64(data) {
return Buffer.from(data).toString("base64");
}
//# sourceMappingURL=encoder.js.map

View File

@@ -0,0 +1,227 @@
import { expect, expectTypeOf, test } from "vitest";
import * as z from "zod/v4";
test("opt passthrough", () => {
const object = z.object({
a: z.lazy(() => z.string()),
b: z.lazy(() => z.string().optional()),
c: z.lazy(() => z.string().default("default")),
});
type ObjectTypeIn = z.input<typeof object>;
expectTypeOf<ObjectTypeIn>().toEqualTypeOf<{
a: string;
b?: string | undefined;
c?: string | undefined;
}>();
type ObjectTypeOut = z.output<typeof object>;
expectTypeOf<ObjectTypeOut>().toEqualTypeOf<{
a: string;
b?: string | undefined;
c: string;
}>();
const result = object.parse(
{
a: "hello",
b: undefined,
},
{ jitless: true }
);
expect(result).toEqual({
a: "hello",
// b: undefined,
c: "default",
});
expect(z.lazy(() => z.string())._zod.optin).toEqual(undefined);
expect(z.lazy(() => z.string())._zod.optout).toEqual(undefined);
expect(z.lazy(() => z.string().optional())._zod.optin).toEqual("optional");
expect(z.lazy(() => z.string().optional())._zod.optout).toEqual("optional");
expect(z.lazy(() => z.string().default("asdf"))._zod.optin).toEqual("optional");
expect(z.lazy(() => z.string().default("asdf"))._zod.optout).toEqual(undefined);
});
////////////// LAZY //////////////
test("schema getter", () => {
z.lazy(() => z.string()).parse("asdf");
});
test("lazy proxy", () => {
const schema = z.lazy(() => z.string())._zod.innerType.min(6);
schema.parse("123456");
expect(schema.safeParse("12345").success).toBe(false);
});
interface Category {
name: string;
subcategories: Category[];
}
const testCategory: Category = {
name: "I",
subcategories: [
{
name: "A",
subcategories: [
{
name: "1",
subcategories: [
{
name: "a",
subcategories: [],
},
],
},
],
},
],
};
test("recursion with z.lazy", () => {
const Category: z.ZodType<Category> = z.lazy(() =>
z.object({
name: z.string(),
subcategories: z.array(Category),
})
);
Category.parse(testCategory);
});
type LinkedList = null | { value: number; next: LinkedList };
const linkedListExample = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null,
},
},
},
};
test("recursive union wit z.lazy", () => {
const LinkedListSchema: z.ZodType<LinkedList> = z.lazy(() =>
z.union([
z.null(),
z.object({
value: z.number(),
next: LinkedListSchema,
}),
])
);
LinkedListSchema.parse(linkedListExample);
});
interface A {
val: number;
b: B;
}
interface B {
val: number;
a?: A | undefined;
}
test("mutual recursion with lazy", () => {
const Alazy: z.ZodType<A> = z.lazy(() =>
z.object({
val: z.number(),
b: Blazy,
})
);
const Blazy: z.ZodType<B> = z.lazy(() =>
z.object({
val: z.number(),
a: Alazy.optional(),
})
);
const testData = {
val: 1,
b: {
val: 5,
a: {
val: 3,
b: {
val: 4,
a: {
val: 2,
b: {
val: 1,
},
},
},
},
},
};
Alazy.parse(testData);
Blazy.parse(testData.b);
expect(() => Alazy.parse({ val: "asdf" })).toThrow();
});
// TODO
test("mutual recursion with cyclical data", () => {
const a: any = { val: 1 };
const b: any = { val: 2 };
a.b = b;
b.a = a;
});
test("complicated self-recursion", () => {
const Category = z.object({
name: z.string(),
age: z.optional(z.number()),
get nullself() {
return Category.nullable();
},
get optself() {
return Category.optional();
},
get self() {
return Category;
},
get subcategories() {
return z.array(Category);
},
nested: z.object({
get sub() {
return Category;
},
}),
});
type _Category = z.output<typeof Category>;
});
test("lazy initialization", () => {
const a: any = z.lazy(() => a).optional();
const b: any = z.lazy(() => b).nullable();
const c: any = z.lazy(() => c).default({} as any);
const d: any = z.lazy(() => d).prefault({} as any);
const e: any = z.lazy(() => e).nonoptional();
const f: any = z.lazy(() => f).catch({} as any);
const g: any = z.lazy(() => z.object({ g })).readonly();
const baseCategorySchema = z.object({
name: z.string(),
});
type Category = z.infer<typeof baseCategorySchema> & {
subcategories: Category[];
};
const categorySchema: z.ZodType<Category> = baseCategorySchema.extend({
subcategories: z.lazy(() => categorySchema.array()),
});
});

View File

@@ -0,0 +1,19 @@
# @babel/runtime
> babel's modular runtime helpers
See our website [@babel/runtime](https://babeljs.io/docs/babel-runtime) for more information.
## Install
Using npm:
```sh
npm install --save @babel/runtime
```
or using yarn:
```sh
yarn add @babel/runtime
```

View File

@@ -0,0 +1,44 @@
'use strict';
const {Transform} = require('stream');
const withParser = require('./withParser');
class Batch extends Transform {
static make(options) {
return new Batch(options);
}
static withParser(options) {
return withParser(Batch.make, options);
}
constructor(options) {
super(Object.assign({}, options, {writableObjectMode: true, readableObjectMode: true}));
this._batchSize = 1000;
if (options && typeof options.batchSize == 'number' && options.batchSize > 0) {
this._batchSize = options.batchSize;
}
this._accumulator = [];
}
_transform(chunk, _, callback) {
this._accumulator.push(chunk);
if (this._accumulator.length >= this._batchSize) {
this.push(this._accumulator);
this._accumulator = [];
}
callback(null);
}
_flush(callback) {
if (this._accumulator.length) {
this.push(this._accumulator);
this._accumulator = null;
}
callback(null);
}
}
Batch.batch = Batch.make;
Batch.make.Constructor = Batch;
module.exports = Batch;

View File

@@ -0,0 +1,46 @@
{
"name": "prelude-ls",
"version": "1.2.1",
"author": "George Zahariev <z@georgezahariev.com>",
"description": "prelude.ls is a functionally oriented utility library. It is powerful and flexible. Almost all of its functions are curried. It is written in, and is the recommended base library for, LiveScript.",
"keywords": [
"prelude",
"livescript",
"utility",
"ls",
"coffeescript",
"javascript",
"library",
"functional",
"array",
"list",
"object",
"string"
],
"main": "lib/",
"files": [
"lib/",
"README.md",
"LICENSE"
],
"homepage": "http://preludels.com",
"bugs": "https://github.com/gkz/prelude-ls/issues",
"license": "MIT",
"engines": {
"node": ">= 0.8.0"
},
"repository": {
"type": "git",
"url": "git://github.com/gkz/prelude-ls.git"
},
"scripts": {
"test": "make test"
},
"devDependencies": {
"livescript": "^1.6.0",
"uglify-js": "^3.8.1",
"mocha": "^7.1.1",
"browserify": "^16.5.1",
"sinon": "~8.0.1"
}
}

View File

@@ -0,0 +1,15 @@
# Changelog
## [1.0.1](https://github.com/humanwhocodes/module-importer/compare/v1.0.0...v1.0.1) (2022-08-18)
### Bug Fixes
* Ensure CommonJS mode works correctly. ([cf54a0b](https://github.com/humanwhocodes/module-importer/commit/cf54a0b998085066fbe1776dd0b4cacd808cc192)), closes [#6](https://github.com/humanwhocodes/module-importer/issues/6)
## 1.0.0 (2022-08-17)
### Features
* Implement ModuleImporter ([3ce4e82](https://www.github.com/humanwhocodes/module-importer/commit/3ce4e820c30c114e787bfed00a0966ac4772f563))

View File

@@ -0,0 +1 @@
{"version":3,"file":"_shortw_utils.js","sourceRoot":"","sources":["../src/_shortw_utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,sEAAsE;AACtE,OAAO,EAAgC,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGtF,4CAA4C;AAC5C,MAAM,UAAU,OAAO,CAAC,IAAW;IACjC,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAKD,gEAAgE;AAChE,MAAM,UAAU,WAAW,CAAC,QAAkB,EAAE,OAAc;IAC5D,MAAM,MAAM,GAAG,CAAC,IAAW,EAAW,EAAE,CAAC,WAAW,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAClF,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;AACxC,CAAC"}

View File

@@ -0,0 +1,204 @@
# dateformat
A node.js package for Steven Levithan's excellent [dateFormat()][dateformat] function.
[![Build Status](https://travis-ci.org/felixge/node-dateformat.svg)](https://travis-ci.org/felixge/node-dateformat)
## Modifications
- Removed the `Date.prototype.format` method. Sorry folks, but extending native prototypes is for suckers.
- Added a `module.exports = dateFormat;` statement at the bottom
- Added the placeholder `N` to get the ISO 8601 numeric representation of the day of the week
## Installation
```bash
$ npm install dateformat
$ dateformat --help
```
## Usage
As taken from Steven's post, modified to match the Modifications listed above:
```js
var dateFormat = require("dateformat");
var now = new Date();
// Basic usage
dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT");
// Saturday, June 9th, 2007, 5:46:21 PM
// You can use one of several named masks
dateFormat(now, "isoDateTime");
// 2007-06-09T17:46:21
// ...Or add your own
dateFormat.masks.hammerTime = 'HH:MM! "Can\'t touch this!"';
dateFormat(now, "hammerTime");
// 17:46! Can't touch this!
// You can also provide the date as a string
dateFormat("Jun 9 2007", "fullDate");
// Saturday, June 9, 2007
// Note that if you don't include the mask argument,
// dateFormat.masks.default is used
dateFormat(now);
// Sat Jun 09 2007 17:46:21
// And if you don't include the date argument,
// the current date and time is used
dateFormat();
// Sat Jun 09 2007 17:46:22
// You can also skip the date argument (as long as your mask doesn't
// contain any numbers), in which case the current date/time is used
dateFormat("longTime");
// 5:46:22 PM EST
// And finally, you can convert local time to UTC time. Simply pass in
// true as an additional argument (no argument skipping allowed in this case):
dateFormat(now, "longTime", true);
// 10:46:21 PM UTC
// ...Or add the prefix "UTC:" or "GMT:" to your mask.
dateFormat(now, "UTC:h:MM:ss TT Z");
// 10:46:21 PM UTC
// You can also get the ISO 8601 week of the year:
dateFormat(now, "W");
// 42
// and also get the ISO 8601 numeric representation of the day of the week:
dateFormat(now, "N");
// 6
```
### Mask options
| Mask | Description |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `d` | Day of the month as digits; no leading zero for single-digit days. |
| `dd` | Day of the month as digits; leading zero for single-digit days. |
| `ddd` | Day of the week as a three-letter abbreviation. |
| `DDD` | "Ysd", "Tdy" or "Tmw" if date lies within these three days. Else fall back to ddd. |
| `dddd` | Day of the week as its full name. |
| `DDDD` | "Yesterday", "Today" or "Tomorrow" if date lies within these three days. Else fall back to dddd. |
| `m` | Month as digits; no leading zero for single-digit months. |
| `mm` | Month as digits; leading zero for single-digit months. |
| `mmm` | Month as a three-letter abbreviation. |
| `mmmm` | Month as its full name. |
| `yy` | Year as last two digits; leading zero for years less than 10. |
| `yyyy` | Year represented by four digits. |
| `h` | Hours; no leading zero for single-digit hours (12-hour clock). |
| `hh` | Hours; leading zero for single-digit hours (12-hour clock). |
| `H` | Hours; no leading zero for single-digit hours (24-hour clock). |
| `HH` | Hours; leading zero for single-digit hours (24-hour clock). |
| `M` | Minutes; no leading zero for single-digit minutes. |
| `MM` | Minutes; leading zero for single-digit minutes. |
| `N` | ISO 8601 numeric representation of the day of the week. |
| `o` | GMT/UTC timezone offset, e.g. -0500 or +0230. |
| `p` | GMT/UTC timezone offset, e.g. -05:00 or +02:30. |
| `s` | Seconds; no leading zero for single-digit seconds. |
| `ss` | Seconds; leading zero for single-digit seconds. |
| `S` | The date's ordinal suffix (st, nd, rd, or th). Works well with `d`. |
| `l` | Milliseconds; gives 3 digits. |
| `L` | Milliseconds; gives 2 digits. |
| `t` | Lowercase, single-character time marker string: a or p. |
| `tt` | Lowercase, two-character time marker string: am or pm. |
| `T` | Uppercase, single-character time marker string: A or P. |
| `TT` | Uppercase, two-character time marker string: AM or PM. |
| `W` | ISO 8601 week number of the year, e.g. 4, 42 |
| `WW` | ISO 8601 week number of the year, leading zero for single-digit, e.g. 04, 42 |
| `Z` | US timezone abbreviation, e.g. EST or MDT. For non-US timezones, the GMT/UTC offset is returned, e.g. GMT-0500 |
| `'...'`, `"..."` | Literal character sequence. Surrounding quotes are removed. |
| `UTC:` | Must be the first four characters of the mask. Converts the date from local time to UTC/GMT/Zulu time before applying the mask. The "UTC:" prefix is removed. |
### Named Formats
| Name | Mask | Example |
| ----------------- | ------------------------------ | ------------------------ |
| `default` | `ddd mmm dd yyyy HH:MM:ss` | Sat Jun 09 2007 17:46:21 |
| `shortDate` | `m/d/yy` | 6/9/07 |
| `paddedShortDate` | `mm/dd/yyyy` | 06/09/2007 |
| `mediumDate` | `mmm d, yyyy` | Jun 9, 2007 |
| `longDate` | `mmmm d, yyyy` | June 9, 2007 |
| `fullDate` | `dddd, mmmm d, yyyy` | Saturday, June 9, 2007 |
| `shortTime` | `h:MM TT` | 5:46 PM |
| `mediumTime` | `h:MM:ss TT` | 5:46:21 PM |
| `longTime` | `h:MM:ss TT Z` | 5:46:21 PM EST |
| `isoDate` | `yyyy-mm-dd` | 2007-06-09 |
| `isoTime` | `HH:MM:ss` | 17:46:21 |
| `isoDateTime` | `yyyy-mm-dd'T'HH:MM:sso` | 2007-06-09T17:46:21+0700 |
| `isoUtcDateTime` | `UTC:yyyy-mm-dd'T'HH:MM:ss'Z'` | 2007-06-09T22:46:21Z |
### Localization
Day names, month names and the AM/PM indicators can be localized by
passing an object with the necessary strings. For example:
```js
var dateFormat = require("dateformat");
dateFormat.i18n = {
dayNames: [
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
],
monthNames: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
],
timeNames: ["a", "p", "am", "pm", "A", "P", "AM", "PM"],
};
```
> Notice that only one language is supported at a time and all strings
> _must_ be present in the new value.
### Breaking change in 2.1.0
- 2.1.0 was published with a breaking change, for those using localized strings.
- 2.2.0 has been published without the change, to keep packages refering to ^2.0.0 to continue working. This is now branch v2_2.
- 3.0.\* contains the localized AM/PM change.
## License
(c) 2007-2009 Steven Levithan [stevenlevithan.com][stevenlevithan], MIT license.
[dateformat]: http://blog.stevenlevithan.com/archives/date-time-format
[stevenlevithan]: http://stevenlevithan.com/

View File

@@ -0,0 +1,27 @@
function _importDeferProxy(e) {
var t = null,
constValue = function constValue(e) {
return function () {
return e;
};
},
proxy = function proxy(r) {
return function (n, o, f) {
return null === t && (t = e()), r(t, o, f);
};
};
return new Proxy({}, {
defineProperty: constValue(!1),
deleteProperty: constValue(!1),
get: proxy(Reflect.get),
getOwnPropertyDescriptor: proxy(Reflect.getOwnPropertyDescriptor),
getPrototypeOf: constValue(null),
isExtensible: constValue(!1),
has: proxy(Reflect.has),
ownKeys: proxy(Reflect.ownKeys),
preventExtensions: constValue(!0),
set: constValue(!1),
setPrototypeOf: constValue(!1)
});
}
module.exports = _importDeferProxy, module.exports.__esModule = true, module.exports["default"] = module.exports;

View File

@@ -0,0 +1,27 @@
import type { Scope } from '../scope';
import type { Variable } from './Variable';
import { ESLintScopeVariable } from './ESLintScopeVariable';
export interface ImplicitLibVariableOptions {
readonly eslintImplicitGlobalSetting?: ESLintScopeVariable['eslintImplicitGlobalSetting'];
readonly isTypeVariable?: boolean;
readonly isValueVariable?: boolean;
readonly writeable?: boolean;
}
export interface LibDefinition {
libs: readonly LibDefinition[];
variables: readonly [string, ImplicitLibVariableOptions][];
}
/**
* An variable implicitly defined by the TS Lib
*/
export declare class ImplicitLibVariable extends ESLintScopeVariable implements Variable {
/**
* `true` if the variable is valid in a type context, false otherwise
*/
readonly isTypeVariable: boolean;
/**
* `true` if the variable is valid in a value context, false otherwise
*/
readonly isValueVariable: boolean;
constructor(scope: Scope, name: string, { eslintImplicitGlobalSetting, isTypeVariable, isValueVariable, writeable, }: ImplicitLibVariableOptions);
}

View File

@@ -0,0 +1,22 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABILITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference lib="es2018" />
/// <reference lib="dom" />
/// <reference lib="webworker.importscripts" />
/// <reference lib="scripthost" />
/// <reference lib="dom.iterable" />
/// <reference lib="dom.asynciterable" />

View File

@@ -0,0 +1,29 @@
'use strict'
module.exports = getLevelLabelData
const { LEVELS, LEVEL_NAMES } = require('../constants')
/**
* Given initial settings for custom levels/names and use of only custom props
* get the level label that corresponds with a given level number
*
* @param {boolean} useOnlyCustomProps
* @param {object} customLevels
* @param {object} customLevelNames
*
* @returns {function} A function that takes a number level and returns the level's label string
*/
function getLevelLabelData (useOnlyCustomProps, customLevels, customLevelNames) {
const levels = useOnlyCustomProps ? customLevels || LEVELS : Object.assign({}, LEVELS, customLevels)
const levelNames = useOnlyCustomProps ? customLevelNames || LEVEL_NAMES : Object.assign({}, LEVEL_NAMES, customLevelNames)
return function (level) {
let levelNum = 'default'
if (Number.isInteger(+level)) {
levelNum = Object.prototype.hasOwnProperty.call(levels, level) ? level : levelNum
} else {
levelNum = Object.prototype.hasOwnProperty.call(levelNames, level.toLowerCase()) ? levelNames[level.toLowerCase()] : levelNum
}
return [levels[levelNum], levelNum]
}
}

View File

@@ -0,0 +1,545 @@
'use strict';
const Utf8Stream = require('./utils/Utf8Stream');
const patterns = {
value1: /^(?:[\"\{\[\]\-\d]|true\b|false\b|null\b|\s{1,256})/,
string: /^(?:[^\x00-\x1f\"\\]{1,256}|\\[bfnrt\"\\\/]|\\u[\da-fA-F]{4}|\")/,
key1: /^(?:[\"\}]|\s{1,256})/,
colon: /^(?:\:|\s{1,256})/,
comma: /^(?:[\,\]\}]|\s{1,256})/,
ws: /^\s{1,256}/,
numberStart: /^\d/,
numberDigit: /^\d{0,256}/,
numberFraction: /^[\.eE]/,
numberExponent: /^[eE]/,
numberExpSign: /^[-+]/
};
const MAX_PATTERN_SIZE = 16;
let noSticky = true;
try {
new RegExp('.', 'y');
noSticky = false;
} catch (e) {
// suppress
}
!noSticky &&
Object.keys(patterns).forEach(key => {
let src = patterns[key].source.slice(1); // lop off ^
if (src.slice(0, 3) === '(?:' && src.slice(-1) === ')') {
src = src.slice(3, -1);
}
patterns[key] = new RegExp(src, 'y');
});
patterns.numberFracStart = patterns.numberExpStart = patterns.numberStart;
patterns.numberFracDigit = patterns.numberExpDigit = patterns.numberDigit;
const values = {true: true, false: false, null: null},
expected = {object: 'objectStop', array: 'arrayStop', '': 'done'};
// long hexadecimal codes: \uXXXX
const fromHex = s => String.fromCharCode(parseInt(s.slice(2), 16));
// short codes: \b \f \n \r \t \" \\ \/
const codes = {b: '\b', f: '\f', n: '\n', r: '\r', t: '\t', '"': '"', '\\': '\\', '/': '/'};
class Parser extends Utf8Stream {
static make(options) {
return new Parser(options);
}
constructor(options) {
super(Object.assign({}, options, {readableObjectMode: true}));
this._packKeys = this._packStrings = this._packNumbers = this._streamKeys = this._streamStrings = this._streamNumbers = true;
if (options) {
'packValues' in options && (this._packKeys = this._packStrings = this._packNumbers = options.packValues);
'packKeys' in options && (this._packKeys = options.packKeys);
'packStrings' in options && (this._packStrings = options.packStrings);
'packNumbers' in options && (this._packNumbers = options.packNumbers);
'streamValues' in options && (this._streamKeys = this._streamStrings = this._streamNumbers = options.streamValues);
'streamKeys' in options && (this._streamKeys = options.streamKeys);
'streamStrings' in options && (this._streamStrings = options.streamStrings);
'streamNumbers' in options && (this._streamNumbers = options.streamNumbers);
this._jsonStreaming = options.jsonStreaming;
}
!this._packKeys && (this._streamKeys = true);
!this._packStrings && (this._streamStrings = true);
!this._packNumbers && (this._streamNumbers = true);
this._done = false;
this._expect = this._jsonStreaming ? 'done' : 'value';
this._stack = [];
this._parent = '';
this._open_number = false;
this._accumulator = '';
}
_flush(callback) {
this._done = true;
super._flush(error => {
if (error) return callback(error);
if (this._open_number) {
if (this._streamNumbers) {
this.push({name: 'endNumber'});
}
this._open_number = false;
if (this._packNumbers) {
this.push({name: 'numberValue', value: this._accumulator});
this._accumulator = '';
}
}
callback(null);
});
}
_processBuffer(callback) {
let match,
value,
index = 0;
main: for (;;) {
switch (this._expect) {
case 'value1':
case 'value':
patterns.value1.lastIndex = index;
match = patterns.value1.exec(this._buffer);
if (!match) {
if (this._done || index + MAX_PATTERN_SIZE < this._buffer.length) {
if (index < this._buffer.length) return callback(new Error('Parser cannot parse input: expected a value'));
return callback(new Error('Parser has expected a value'));
}
break main; // wait for more input
}
value = match[0];
switch (value) {
case '"':
this._streamStrings && this.push({name: 'startString'});
this._expect = 'string';
break;
case '{':
this.push({name: 'startObject'});
this._stack.push(this._parent);
this._parent = 'object';
this._expect = 'key1';
break;
case '[':
this.push({name: 'startArray'});
this._stack.push(this._parent);
this._parent = 'array';
this._expect = 'value1';
break;
case ']':
if (this._expect !== 'value1') return callback(new Error("Parser cannot parse input: unexpected token ']'"));
if (this._open_number) {
this._streamNumbers && this.push({name: 'endNumber'});
this._open_number = false;
if (this._packNumbers) {
this.push({name: 'numberValue', value: this._accumulator});
this._accumulator = '';
}
}
this.push({name: 'endArray'});
this._parent = this._stack.pop();
this._expect = expected[this._parent];
break;
case '-':
this._open_number = true;
if (this._streamNumbers) {
this.push({name: 'startNumber'});
this.push({name: 'numberChunk', value: '-'});
}
this._packNumbers && (this._accumulator = '-');
this._expect = 'numberStart';
break;
case '0':
this._open_number = true;
if (this._streamNumbers) {
this.push({name: 'startNumber'});
this.push({name: 'numberChunk', value: '0'});
}
this._packNumbers && (this._accumulator = '0');
this._expect = 'numberFraction';
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
this._open_number = true;
if (this._streamNumbers) {
this.push({name: 'startNumber'});
this.push({name: 'numberChunk', value: value});
}
this._packNumbers && (this._accumulator = value);
this._expect = 'numberDigit';
break;
case 'true':
case 'false':
case 'null':
if (this._buffer.length - index === value.length && !this._done) break main; // wait for more input
this.push({name: value + 'Value', value: values[value]});
this._expect = expected[this._parent];
break;
// default: // ws
}
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'keyVal':
case 'string':
patterns.string.lastIndex = index;
match = patterns.string.exec(this._buffer);
if (!match) {
if (index < this._buffer.length && (this._done || this._buffer.length - index >= 6))
return callback(new Error('Parser cannot parse input: escaped characters'));
if (this._done) return callback(new Error('Parser has expected a string value'));
break main; // wait for more input
}
value = match[0];
if (value === '"') {
if (this._expect === 'keyVal') {
this._streamKeys && this.push({name: 'endKey'});
if (this._packKeys) {
this.push({name: 'keyValue', value: this._accumulator});
this._accumulator = '';
}
this._expect = 'colon';
} else {
this._streamStrings && this.push({name: 'endString'});
if (this._packStrings) {
this.push({name: 'stringValue', value: this._accumulator});
this._accumulator = '';
}
this._expect = expected[this._parent];
}
} else if (value.length > 1 && value.charAt(0) === '\\') {
const t = value.length == 2 ? codes[value.charAt(1)] : fromHex(value);
if (this._expect === 'keyVal' ? this._streamKeys : this._streamStrings) {
this.push({name: 'stringChunk', value: t});
}
if (this._expect === 'keyVal' ? this._packKeys : this._packStrings) {
this._accumulator += t;
}
} else {
if (this._expect === 'keyVal' ? this._streamKeys : this._streamStrings) {
this.push({name: 'stringChunk', value: value});
}
if (this._expect === 'keyVal' ? this._packKeys : this._packStrings) {
this._accumulator += value;
}
}
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'key1':
case 'key':
patterns.key1.lastIndex = index;
match = patterns.key1.exec(this._buffer);
if (!match) {
if (index < this._buffer.length || this._done) return callback(new Error('Parser cannot parse input: expected an object key'));
break main; // wait for more input
}
value = match[0];
if (value === '"') {
this._streamKeys && this.push({name: 'startKey'});
this._expect = 'keyVal';
} else if (value === '}') {
if (this._expect !== 'key1') return callback(new Error("Parser cannot parse input: unexpected token '}'"));
this.push({name: 'endObject'});
this._parent = this._stack.pop();
this._expect = expected[this._parent];
}
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'colon':
patterns.colon.lastIndex = index;
match = patterns.colon.exec(this._buffer);
if (!match) {
if (index < this._buffer.length || this._done) return callback(new Error("Parser cannot parse input: expected ':'"));
break main; // wait for more input
}
value = match[0];
value === ':' && (this._expect = 'value');
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'arrayStop':
case 'objectStop':
patterns.comma.lastIndex = index;
match = patterns.comma.exec(this._buffer);
if (!match) {
if (index < this._buffer.length || this._done) return callback(new Error("Parser cannot parse input: expected ','"));
break main; // wait for more input
}
if (this._open_number) {
this._streamNumbers && this.push({name: 'endNumber'});
this._open_number = false;
if (this._packNumbers) {
this.push({name: 'numberValue', value: this._accumulator});
this._accumulator = '';
}
}
value = match[0];
if (value === ',') {
this._expect = this._expect === 'arrayStop' ? 'value' : 'key';
} else if (value === '}' || value === ']') {
if (value === '}' ? this._expect === 'arrayStop' : this._expect !== 'arrayStop') {
return callback(new Error("Parser cannot parse input: expected '" + (this._expect === 'arrayStop' ? ']' : '}') + "'"));
}
this.push({name: value === '}' ? 'endObject' : 'endArray'});
this._parent = this._stack.pop();
this._expect = expected[this._parent];
}
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
// number chunks
case 'numberStart': // [0-9]
patterns.numberStart.lastIndex = index;
match = patterns.numberStart.exec(this._buffer);
if (!match) {
if (index < this._buffer.length || this._done) return callback(new Error('Parser cannot parse input: expected a starting digit'));
break main; // wait for more input
}
value = match[0];
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
this._expect = value === '0' ? 'numberFraction' : 'numberDigit';
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'numberDigit': // [0-9]*
patterns.numberDigit.lastIndex = index;
match = patterns.numberDigit.exec(this._buffer);
if (!match) {
if (index < this._buffer.length || this._done) return callback(new Error('Parser cannot parse input: expected a digit'));
break main; // wait for more input
}
value = match[0];
if (value) {
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
} else {
if (index < this._buffer.length) {
this._expect = 'numberFraction';
break;
}
if (this._done) {
this._expect = expected[this._parent];
break;
}
break main; // wait for more input
}
break;
case 'numberFraction': // [\.eE]?
patterns.numberFraction.lastIndex = index;
match = patterns.numberFraction.exec(this._buffer);
if (!match) {
if (index < this._buffer.length || this._done) {
this._expect = expected[this._parent];
break;
}
break main; // wait for more input
}
value = match[0];
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
this._expect = value === '.' ? 'numberFracStart' : 'numberExpSign';
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'numberFracStart': // [0-9]
patterns.numberFracStart.lastIndex = index;
match = patterns.numberFracStart.exec(this._buffer);
if (!match) {
if (index < this._buffer.length || this._done) return callback(new Error('Parser cannot parse input: expected a fractional part of a number'));
break main; // wait for more input
}
value = match[0];
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
this._expect = 'numberFracDigit';
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'numberFracDigit': // [0-9]*
patterns.numberFracDigit.lastIndex = index;
match = patterns.numberFracDigit.exec(this._buffer);
value = match[0];
if (value) {
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
} else {
if (index < this._buffer.length) {
this._expect = 'numberExponent';
break;
}
if (this._done) {
this._expect = expected[this._parent];
break;
}
break main; // wait for more input
}
break;
case 'numberExponent': // [eE]?
patterns.numberExponent.lastIndex = index;
match = patterns.numberExponent.exec(this._buffer);
if (!match) {
if (index < this._buffer.length) {
this._expect = expected[this._parent];
break;
}
if (this._done) {
this._expect = 'done';
break;
}
break main; // wait for more input
}
value = match[0];
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
this._expect = 'numberExpSign';
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'numberExpSign': // [-+]?
patterns.numberExpSign.lastIndex = index;
match = patterns.numberExpSign.exec(this._buffer);
if (!match) {
if (index < this._buffer.length) {
this._expect = 'numberExpStart';
break;
}
if (this._done) return callback(new Error('Parser has expected an exponent value of a number'));
break main; // wait for more input
}
value = match[0];
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
this._expect = 'numberExpStart';
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'numberExpStart': // [0-9]
patterns.numberExpStart.lastIndex = index;
match = patterns.numberExpStart.exec(this._buffer);
if (!match) {
if (index < this._buffer.length || this._done) return callback(new Error('Parser cannot parse input: expected an exponent part of a number'));
break main; // wait for more input
}
value = match[0];
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
this._expect = 'numberExpDigit';
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
case 'numberExpDigit': // [0-9]*
patterns.numberExpDigit.lastIndex = index;
match = patterns.numberExpDigit.exec(this._buffer);
value = match[0];
if (value) {
this._streamNumbers && this.push({name: 'numberChunk', value: value});
this._packNumbers && (this._accumulator += value);
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
} else {
if (index < this._buffer.length || this._done) {
this._expect = expected[this._parent];
break;
}
break main; // wait for more input
}
break;
case 'done':
patterns.ws.lastIndex = index;
match = patterns.ws.exec(this._buffer);
if (!match) {
if (index < this._buffer.length) {
if (this._jsonStreaming) {
this._expect = 'value';
break;
}
return callback(new Error('Parser cannot parse input: unexpected characters'));
}
break main; // wait for more input
}
value = match[0];
if (this._open_number) {
this._streamNumbers && this.push({name: 'endNumber'});
this._open_number = false;
if (this._packNumbers) {
this.push({name: 'numberValue', value: this._accumulator});
this._accumulator = '';
}
}
if (noSticky) {
this._buffer = this._buffer.slice(value.length);
} else {
index += value.length;
}
break;
}
}
!noSticky && (this._buffer = this._buffer.slice(index));
callback(null);
}
}
Parser.parser = Parser.make;
Parser.make.Constructor = Parser;
module.exports = Parser;

View File

@@ -0,0 +1,2 @@
export * from './compilerOptions';
export * from './getParsedConfigFile';

View File

@@ -0,0 +1,22 @@
declare module 'buffer' {
export const INSPECT_MAX_BYTES: number;
export const kMaxLength: number;
export const kStringMaxLength: number;
export const constants: {
MAX_LENGTH: number;
MAX_STRING_LENGTH: number;
};
const BuffType: typeof Buffer;
export type TranscodeEncoding = "ascii" | "utf8" | "utf16le" | "ucs2" | "latin1" | "binary";
export function transcode(source: Uint8Array, fromEnc: TranscodeEncoding, toEnc: TranscodeEncoding): Buffer;
export const SlowBuffer: {
/** @deprecated since v6.0.0, use Buffer.allocUnsafeSlow() */
new(size: number): Buffer;
prototype: Buffer;
};
export { BuffType as Buffer };
}

View File

@@ -0,0 +1,262 @@
/**
* @fileoverview Rule to flag the use of redundant constructors in classes.
* @author Alberto Rodríguez
*/
"use strict";
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Checks whether any of a method's parameters have a decorator or are a parameter property.
* @param {ASTNode} node A method definition node.
* @returns {boolean} `true` if any parameter had a decorator or is a parameter property.
*/
function hasDecoratorsOrParameterProperty(node) {
return node.value.params.some(
param =>
param.decorators?.length || param.type === "TSParameterProperty",
);
}
/**
* Checks whether a node's accessibility makes it not useless.
* @param {ASTNode} node A method definition node.
* @returns {boolean} `true` if the node has a useful accessibility.
*/
function hasUsefulAccessibility(node) {
switch (node.accessibility) {
case "protected":
case "private":
return true;
case "public":
return !!node.parent.parent.superClass;
default:
return false;
}
}
/**
* Checks whether a given array of statements is a single call of `super`.
* @param {ASTNode[]} body An array of statements to check.
* @returns {boolean} `true` if the body is a single call of `super`.
*/
function isSingleSuperCall(body) {
return (
body.length === 1 &&
body[0].type === "ExpressionStatement" &&
body[0].expression.type === "CallExpression" &&
body[0].expression.callee.type === "Super"
);
}
/**
* Checks whether a given node is a pattern which doesn't have any side effects.
* Default parameters and Destructuring parameters can have side effects.
* @param {ASTNode} node A pattern node.
* @returns {boolean} `true` if the node doesn't have any side effects.
*/
function isSimple(node) {
return node.type === "Identifier" || node.type === "RestElement";
}
/**
* Checks whether a given array of expressions is `...arguments` or not.
* `super(...arguments)` passes all arguments through.
* @param {ASTNode[]} superArgs An array of expressions to check.
* @returns {boolean} `true` if the superArgs is `...arguments`.
*/
function isSpreadArguments(superArgs) {
return (
superArgs.length === 1 &&
superArgs[0].type === "SpreadElement" &&
superArgs[0].argument.type === "Identifier" &&
superArgs[0].argument.name === "arguments"
);
}
/**
* Checks whether given 2 nodes are identifiers which have the same name or not.
* @param {ASTNode} ctorParam A node to check.
* @param {ASTNode} superArg A node to check.
* @returns {boolean} `true` if the nodes are identifiers which have the same
* name.
*/
function isValidIdentifierPair(ctorParam, superArg) {
return (
ctorParam.type === "Identifier" &&
superArg.type === "Identifier" &&
ctorParam.name === superArg.name
);
}
/**
* Checks whether given 2 nodes are a rest/spread pair which has the same values.
* @param {ASTNode} ctorParam A node to check.
* @param {ASTNode} superArg A node to check.
* @returns {boolean} `true` if the nodes are a rest/spread pair which has the
* same values.
*/
function isValidRestSpreadPair(ctorParam, superArg) {
return (
ctorParam.type === "RestElement" &&
superArg.type === "SpreadElement" &&
isValidIdentifierPair(ctorParam.argument, superArg.argument)
);
}
/**
* Checks whether given 2 nodes have the same value or not.
* @param {ASTNode} ctorParam A node to check.
* @param {ASTNode} superArg A node to check.
* @returns {boolean} `true` if the nodes have the same value or not.
*/
function isValidPair(ctorParam, superArg) {
return (
isValidIdentifierPair(ctorParam, superArg) ||
isValidRestSpreadPair(ctorParam, superArg)
);
}
/**
* Checks whether the parameters of a constructor and the arguments of `super()`
* have the same values or not.
* @param {ASTNode} ctorParams The parameters of a constructor to check.
* @param {ASTNode} superArgs The arguments of `super()` to check.
* @returns {boolean} `true` if those have the same values.
*/
function isPassingThrough(ctorParams, superArgs) {
if (ctorParams.length !== superArgs.length) {
return false;
}
for (let i = 0; i < ctorParams.length; ++i) {
if (!isValidPair(ctorParams[i], superArgs[i])) {
return false;
}
}
return true;
}
/**
* Checks whether the constructor body is a redundant super call.
* @param {Array} body constructor body content.
* @param {Array} ctorParams The params to check against super call.
* @returns {boolean} true if the constructor body is redundant
*/
function isRedundantSuperCall(body, ctorParams) {
return (
isSingleSuperCall(body) &&
ctorParams.every(isSimple) &&
(isSpreadArguments(body[0].expression.arguments) ||
isPassingThrough(ctorParams, body[0].expression.arguments))
);
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Disallow unnecessary constructors",
dialects: ["JavaScript", "TypeScript"],
recommended: false,
url: "https://eslint.org/docs/latest/rules/no-useless-constructor",
},
hasSuggestions: true,
schema: [],
messages: {
noUselessConstructor: "Useless constructor.",
removeConstructor: "Remove the constructor.",
},
},
create(context) {
const { sourceCode } = context;
/**
* Checks whether a node is a redundant constructor
* @param {ASTNode} node node to check
* @returns {void}
*/
function checkForConstructor(node) {
if (
node.kind !== "constructor" ||
node.value.type !== "FunctionExpression" ||
hasDecoratorsOrParameterProperty(node) ||
hasUsefulAccessibility(node)
) {
return;
}
/*
* Prevent crashing on parsers which do not require class constructor
* to have a body, e.g. typescript and flow
*/
if (!node.value.body) {
return;
}
const body = node.value.body.body;
const ctorParams = node.value.params;
const superClass = node.parent.parent.superClass;
const parenToken = sourceCode.getFirstToken(
node,
astUtils.isOpeningParenToken,
);
const loc = {
start: node.loc.start,
end: sourceCode.getTokenBefore(parenToken).loc.end,
};
if (
superClass
? isRedundantSuperCall(body, ctorParams)
: body.length === 0
) {
context.report({
loc,
messageId: "noUselessConstructor",
suggest: [
{
messageId: "removeConstructor",
*fix(fixer) {
const nextToken =
sourceCode.getTokenAfter(node);
const addSemiColon =
astUtils.canContinueExpressionInClassBody(
nextToken,
) &&
astUtils.needsPrecedingSemicolon(
sourceCode,
node,
);
yield fixer.replaceText(
node,
addSemiColon ? ";" : "",
);
},
},
],
});
}
}
return {
MethodDefinition: checkForConstructor,
};
},
};

View File

@@ -0,0 +1,102 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const scope_manager_1 = require("@typescript-eslint/scope-manager");
const utils_1 = require("@typescript-eslint/utils");
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'no-empty-interface',
meta: {
type: 'suggestion',
deprecated: {
deprecatedSince: '8.0.0',
replacedBy: [
{
rule: {
name: '@typescript-eslint/no-empty-object-type',
url: 'https://typescript-eslint.io/rules/no-empty-object-type',
},
},
],
url: 'https://github.com/typescript-eslint/typescript-eslint/pull/8977',
},
docs: {
description: 'Disallow the declaration of empty interfaces',
},
fixable: 'code',
hasSuggestions: true,
messages: {
noEmpty: 'An empty interface is equivalent to `{}`.',
noEmptyWithSuper: 'An interface declaring no members is equivalent to its supertype.',
},
replacedBy: ['@typescript-eslint/no-empty-object-type'],
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
allowSingleExtends: {
type: 'boolean',
description: 'Whether to allow empty interfaces that extend a single other interface.',
},
},
},
],
},
defaultOptions: [
{
allowSingleExtends: false,
},
],
create(context, [{ allowSingleExtends }]) {
return {
TSInterfaceDeclaration(node) {
if (node.body.body.length !== 0) {
// interface contains members --> Nothing to report
return;
}
const extend = node.extends;
if (extend.length === 0) {
context.report({
node: node.id,
messageId: 'noEmpty',
});
}
else if (extend.length === 1 &&
// interface extends exactly 1 interface --> Report depending on rule setting
!allowSingleExtends) {
const fix = (fixer) => {
let typeParam = '';
if (node.typeParameters) {
typeParam = context.sourceCode.getText(node.typeParameters);
}
return fixer.replaceText(node, `type ${context.sourceCode.getText(node.id)}${typeParam} = ${context.sourceCode.getText(extend[0])}`);
};
const scope = context.sourceCode.getScope(node);
const mergedWithClassDeclaration = scope.set
.get(node.id.name)
?.defs.some(def => def.node.type === utils_1.AST_NODE_TYPES.ClassDeclaration);
const isInAmbientDeclaration = (0, util_1.isDefinitionFile)(context.filename) &&
scope.type === scope_manager_1.ScopeType.tsModule &&
scope.block.declare;
const useAutoFix = !(isInAmbientDeclaration || mergedWithClassDeclaration);
context.report({
node: node.id,
messageId: 'noEmptyWithSuper',
...(useAutoFix
? { fix }
: !mergedWithClassDeclaration
? {
suggest: [
{
messageId: 'noEmptyWithSuper',
fix,
},
],
}
: null),
});
}
},
};
},
});

View File

@@ -0,0 +1,10 @@
function _toSetter(t, e, n) {
e || (e = []);
var r = e.length++;
return Object.defineProperty({}, "_", {
set: function set(o) {
e[r] = o, t.apply(n, e);
}
});
}
module.exports = _toSetter, module.exports.__esModule = true, module.exports["default"] = module.exports;