WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
import validate from './validate.js';
|
||||
|
||||
function version(uuid) {
|
||||
if (!validate(uuid)) {
|
||||
throw TypeError('Invalid UUID');
|
||||
}
|
||||
|
||||
return parseInt(uuid.substr(14, 1), 16);
|
||||
}
|
||||
|
||||
export default version;
|
||||
@@ -0,0 +1,20 @@
|
||||
"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.es2018_asynciterable = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
const es2015_iterable_1 = require("./es2015.iterable");
|
||||
const es2015_symbol_1 = require("./es2015.symbol");
|
||||
exports.es2018_asynciterable = {
|
||||
libs: [es2015_symbol_1.es2015_symbol, es2015_iterable_1.es2015_iterable],
|
||||
variables: [
|
||||
['SymbolConstructor', base_config_1.TYPE],
|
||||
['AsyncIterator', base_config_1.TYPE],
|
||||
['AsyncIterable', base_config_1.TYPE],
|
||||
['AsyncIterableIterator', base_config_1.TYPE],
|
||||
['AsyncIteratorObject', base_config_1.TYPE],
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @fileoverview Virtual file
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @typedef {import("@eslint/core").File} File */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines if a given value has a byte order mark (BOM).
|
||||
* @param {string|Uint8Array} value The value to check.
|
||||
* @returns {boolean} `true` if the value has a BOM, `false` otherwise.
|
||||
*/
|
||||
function hasUnicodeBOM(value) {
|
||||
return typeof value === "string"
|
||||
? value.charCodeAt(0) === 0xfeff
|
||||
: value[0] === 0xef && value[1] === 0xbb && value[2] === 0xbf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips Unicode BOM from the given value.
|
||||
* @param {string|Uint8Array} value The value to remove the BOM from.
|
||||
* @returns {string|Uint8Array} The stripped value.
|
||||
*/
|
||||
function stripUnicodeBOM(value) {
|
||||
if (!hasUnicodeBOM(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
/*
|
||||
* Check Unicode BOM.
|
||||
* In JavaScript, string data is stored as UTF-16, so BOM is 0xFEFF.
|
||||
* https://262.ecma-international.org/6.0/#sec-unicode-format-control-characters
|
||||
*/
|
||||
return value.slice(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* In a Uint8Array, the BOM is represented by three bytes: 0xEF, 0xBB, and 0xBF,
|
||||
* so we can just remove the first three bytes.
|
||||
*/
|
||||
return value.slice(3);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Exports
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Represents a virtual file inside of ESLint.
|
||||
* @implements {File}
|
||||
*/
|
||||
class VFile {
|
||||
/**
|
||||
* The file path including any processor-created virtual path.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
path;
|
||||
|
||||
/**
|
||||
* The file path on disk.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
physicalPath;
|
||||
|
||||
/**
|
||||
* The file contents.
|
||||
* @type {string|Uint8Array}
|
||||
* @readonly
|
||||
*/
|
||||
body;
|
||||
|
||||
/**
|
||||
* The raw body of the file, including a BOM if present.
|
||||
* @type {string|Uint8Array}
|
||||
* @readonly
|
||||
*/
|
||||
rawBody;
|
||||
|
||||
/**
|
||||
* Indicates whether the file has a byte order mark (BOM).
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
bom;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} path The file path.
|
||||
* @param {string|Uint8Array} body The file contents.
|
||||
* @param {Object} [options] Additional options.
|
||||
* @param {string} [options.physicalPath] The file path on disk.
|
||||
*/
|
||||
constructor(path, body, { physicalPath } = {}) {
|
||||
this.path = path;
|
||||
this.physicalPath = physicalPath ?? path;
|
||||
this.bom = hasUnicodeBOM(body);
|
||||
this.body = stripUnicodeBOM(body);
|
||||
this.rawBody = body;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { VFile };
|
||||
@@ -0,0 +1,139 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = default_1;
|
||||
const util = __importStar(require("../core/util.cjs"));
|
||||
const error = () => {
|
||||
const Sizable = {
|
||||
string: { unit: "merkkiä", subject: "merkkijonon" },
|
||||
file: { unit: "tavua", subject: "tiedoston" },
|
||||
array: { unit: "alkiota", subject: "listan" },
|
||||
set: { unit: "alkiota", subject: "joukon" },
|
||||
number: { unit: "", subject: "luvun" },
|
||||
bigint: { unit: "", subject: "suuren kokonaisluvun" },
|
||||
int: { unit: "", subject: "kokonaisluvun" },
|
||||
date: { unit: "", subject: "päivämäärän" },
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "säännöllinen lauseke",
|
||||
email: "sähköpostiosoite",
|
||||
url: "URL-osoite",
|
||||
emoji: "emoji",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "ISO-aikaleima",
|
||||
date: "ISO-päivämäärä",
|
||||
time: "ISO-aika",
|
||||
duration: "ISO-kesto",
|
||||
ipv4: "IPv4-osoite",
|
||||
ipv6: "IPv6-osoite",
|
||||
cidrv4: "IPv4-alue",
|
||||
cidrv6: "IPv6-alue",
|
||||
base64: "base64-koodattu merkkijono",
|
||||
base64url: "base64url-koodattu merkkijono",
|
||||
json_string: "JSON-merkkijono",
|
||||
e164: "E.164-luku",
|
||||
jwt: "JWT",
|
||||
template_literal: "templaattimerkkijono",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
};
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `Virheellinen tyyppi: odotettiin instanceof ${issue.expected}, oli ${received}`;
|
||||
}
|
||||
return `Virheellinen tyyppi: odotettiin ${expected}, oli ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Virheellinen syöte: täytyy olla ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Virheellinen valinta: täytyy olla yksi seuraavista: ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Liian suuri: ${sizing.subject} täytyy olla ${adj}${issue.maximum.toString()} ${sizing.unit}`.trim();
|
||||
}
|
||||
return `Liian suuri: arvon täytyy olla ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Liian pieni: ${sizing.subject} täytyy olla ${adj}${issue.minimum.toString()} ${sizing.unit}`.trim();
|
||||
}
|
||||
return `Liian pieni: arvon täytyy olla ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with")
|
||||
return `Virheellinen syöte: täytyy alkaa "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with")
|
||||
return `Virheellinen syöte: täytyy loppua "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes")
|
||||
return `Virheellinen syöte: täytyy sisältää "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") {
|
||||
return `Virheellinen syöte: täytyy vastata säännöllistä lauseketta ${_issue.pattern}`;
|
||||
}
|
||||
return `Virheellinen ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Virheellinen luku: täytyy olla luvun ${issue.divisor} monikerta`;
|
||||
case "unrecognized_keys":
|
||||
return `${issue.keys.length > 1 ? "Tuntemattomat avaimet" : "Tuntematon avain"}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return "Virheellinen avain tietueessa";
|
||||
case "invalid_union":
|
||||
return "Virheellinen unioni";
|
||||
case "invalid_element":
|
||||
return "Virheellinen arvo joukossa";
|
||||
default:
|
||||
return `Virheellinen syöte`;
|
||||
}
|
||||
};
|
||||
};
|
||||
function default_1() {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
module.exports = exports.default;
|
||||
@@ -0,0 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const outside = require('./outside')
|
||||
// Determine if version is less than all the versions possible in the range
|
||||
const ltr = (version, range, options) => outside(version, range, '<', options)
|
||||
module.exports = ltr
|
||||
@@ -0,0 +1,327 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow using `Object.assign` with an object literal as the first argument and prefer the use of object spread instead
|
||||
* @author Sharmila Jesupaul
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { CALL, ReferenceTracker } = require("@eslint-community/eslint-utils");
|
||||
const {
|
||||
isCommaToken,
|
||||
isOpeningParenToken,
|
||||
isClosingParenToken,
|
||||
isParenthesised,
|
||||
isStartOfExpressionStatement,
|
||||
needsPrecedingSemicolon,
|
||||
} = require("./utils/ast-utils");
|
||||
|
||||
const ANY_SPACE = /\s/u;
|
||||
|
||||
/**
|
||||
* Helper that checks if the Object.assign call has array spread
|
||||
* @param {ASTNode} node The node that the rule warns on
|
||||
* @returns {boolean} - Returns true if the Object.assign call has array spread
|
||||
*/
|
||||
function hasArraySpread(node) {
|
||||
return node.arguments.some(arg => arg.type === "SpreadElement");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given node is an accessor property (getter/setter).
|
||||
* @param {ASTNode} node Node to check.
|
||||
* @returns {boolean} `true` if the node is a getter or a setter.
|
||||
*/
|
||||
function isAccessorProperty(node) {
|
||||
return (
|
||||
node.type === "Property" && (node.kind === "get" || node.kind === "set")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given object expression node has accessor properties (getters/setters).
|
||||
* @param {ASTNode} node `ObjectExpression` node to check.
|
||||
* @returns {boolean} `true` if the node has at least one getter/setter.
|
||||
*/
|
||||
function hasAccessors(node) {
|
||||
return node.properties.some(isAccessorProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given call expression node has object expression arguments with accessor properties (getters/setters).
|
||||
* @param {ASTNode} node `CallExpression` node to check.
|
||||
* @returns {boolean} `true` if the node has at least one argument that is an object expression with at least one getter/setter.
|
||||
*/
|
||||
function hasArgumentsWithAccessors(node) {
|
||||
return node.arguments
|
||||
.filter(arg => arg.type === "ObjectExpression")
|
||||
.some(hasAccessors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that checks if the node needs parentheses to be valid JS.
|
||||
* The default is to wrap the node in parentheses to avoid parsing errors.
|
||||
* @param {ASTNode} node The node that the rule warns on
|
||||
* @param {Object} sourceCode in context sourcecode object
|
||||
* @returns {boolean} - Returns true if the node needs parentheses
|
||||
*/
|
||||
function needsParens(node, sourceCode) {
|
||||
const parent = node.parent;
|
||||
|
||||
switch (parent.type) {
|
||||
case "VariableDeclarator":
|
||||
case "ArrayExpression":
|
||||
case "ReturnStatement":
|
||||
case "CallExpression":
|
||||
case "Property":
|
||||
return false;
|
||||
case "AssignmentExpression":
|
||||
return parent.left === node && !isParenthesised(sourceCode, node);
|
||||
default:
|
||||
return !isParenthesised(sourceCode, node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an argument needs parentheses. The default is to not add parens.
|
||||
* @param {ASTNode} node The node to be checked.
|
||||
* @param {Object} sourceCode in context sourcecode object
|
||||
* @returns {boolean} True if the node needs parentheses
|
||||
*/
|
||||
function argNeedsParens(node, sourceCode) {
|
||||
switch (node.type) {
|
||||
case "AssignmentExpression":
|
||||
case "ArrowFunctionExpression":
|
||||
case "ConditionalExpression":
|
||||
return !isParenthesised(sourceCode, node);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parenthesis tokens of a given ObjectExpression node.
|
||||
* This includes the braces of the object literal and enclosing parentheses.
|
||||
* @param {ASTNode} node The node to get.
|
||||
* @param {Token} leftArgumentListParen The opening paren token of the argument list.
|
||||
* @param {SourceCode} sourceCode The source code object to get tokens.
|
||||
* @returns {Token[]} The parenthesis tokens of the node. This is sorted by the location.
|
||||
*/
|
||||
function getParenTokens(node, leftArgumentListParen, sourceCode) {
|
||||
const parens = [
|
||||
sourceCode.getFirstToken(node),
|
||||
sourceCode.getLastToken(node),
|
||||
];
|
||||
let leftNext = sourceCode.getTokenBefore(node);
|
||||
let rightNext = sourceCode.getTokenAfter(node);
|
||||
|
||||
// Note: don't include the parens of the argument list.
|
||||
while (
|
||||
leftNext &&
|
||||
rightNext &&
|
||||
leftNext.range[0] > leftArgumentListParen.range[0] &&
|
||||
isOpeningParenToken(leftNext) &&
|
||||
isClosingParenToken(rightNext)
|
||||
) {
|
||||
parens.push(leftNext, rightNext);
|
||||
leftNext = sourceCode.getTokenBefore(leftNext);
|
||||
rightNext = sourceCode.getTokenAfter(rightNext);
|
||||
}
|
||||
|
||||
return parens.sort((a, b) => a.range[0] - b.range[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range of a given token and around whitespaces.
|
||||
* @param {Token} token The token to get range.
|
||||
* @param {SourceCode} sourceCode The source code object to get tokens.
|
||||
* @returns {number} The end of the range of the token and around whitespaces.
|
||||
*/
|
||||
function getStartWithSpaces(token, sourceCode) {
|
||||
const text = sourceCode.text;
|
||||
let start = token.range[0];
|
||||
|
||||
// If the previous token is a line comment then skip this step to avoid commenting this token out.
|
||||
{
|
||||
const prevToken = sourceCode.getTokenBefore(token, {
|
||||
includeComments: true,
|
||||
});
|
||||
|
||||
if (prevToken && prevToken.type === "Line") {
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect spaces before the token.
|
||||
while (ANY_SPACE.test(text[start - 1] || "")) {
|
||||
start -= 1;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range of a given token and around whitespaces.
|
||||
* @param {Token} token The token to get range.
|
||||
* @param {SourceCode} sourceCode The source code object to get tokens.
|
||||
* @returns {number} The start of the range of the token and around whitespaces.
|
||||
*/
|
||||
function getEndWithSpaces(token, sourceCode) {
|
||||
const text = sourceCode.text;
|
||||
let end = token.range[1];
|
||||
|
||||
// Detect spaces after the token.
|
||||
while (ANY_SPACE.test(text[end] || "")) {
|
||||
end += 1;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Autofixes the Object.assign call to use an object spread instead.
|
||||
* @param {ASTNode|null} node The node that the rule warns on, i.e. the Object.assign call
|
||||
* @param {string} sourceCode sourceCode of the Object.assign call
|
||||
* @returns {Function} autofixer - replaces the Object.assign with a spread object.
|
||||
*/
|
||||
function defineFixer(node, sourceCode) {
|
||||
return function* (fixer) {
|
||||
const leftParen = sourceCode.getTokenAfter(
|
||||
node.callee,
|
||||
isOpeningParenToken,
|
||||
);
|
||||
const rightParen = sourceCode.getLastToken(node);
|
||||
|
||||
// Remove everything before the opening paren: callee `Object.assign`, type arguments, and whitespace between the callee and the paren.
|
||||
yield fixer.removeRange([node.range[0], leftParen.range[0]]);
|
||||
|
||||
// Replace the parens of argument list to braces.
|
||||
if (needsParens(node, sourceCode)) {
|
||||
const prefix =
|
||||
isStartOfExpressionStatement(node) &&
|
||||
needsPrecedingSemicolon(sourceCode, node)
|
||||
? ";({"
|
||||
: "({";
|
||||
|
||||
yield fixer.replaceText(leftParen, prefix);
|
||||
yield fixer.replaceText(rightParen, "})");
|
||||
} else {
|
||||
yield fixer.replaceText(leftParen, "{");
|
||||
yield fixer.replaceText(rightParen, "}");
|
||||
}
|
||||
|
||||
// Process arguments.
|
||||
for (const argNode of node.arguments) {
|
||||
const innerParens = getParenTokens(argNode, leftParen, sourceCode);
|
||||
const left = innerParens.shift();
|
||||
const right = innerParens.pop();
|
||||
|
||||
if (argNode.type === "ObjectExpression") {
|
||||
const maybeTrailingComma = sourceCode.getLastToken(argNode, 1);
|
||||
const maybeArgumentComma = sourceCode.getTokenAfter(right);
|
||||
|
||||
/*
|
||||
* Make bare this object literal.
|
||||
* And remove spaces inside of the braces for better formatting.
|
||||
*/
|
||||
for (const innerParen of innerParens) {
|
||||
yield fixer.remove(innerParen);
|
||||
}
|
||||
const leftRange = [
|
||||
left.range[0],
|
||||
getEndWithSpaces(left, sourceCode),
|
||||
];
|
||||
const rightRange = [
|
||||
Math.max(
|
||||
getStartWithSpaces(right, sourceCode),
|
||||
leftRange[1],
|
||||
), // Ensure ranges don't overlap
|
||||
right.range[1],
|
||||
];
|
||||
|
||||
yield fixer.removeRange(leftRange);
|
||||
yield fixer.removeRange(rightRange);
|
||||
|
||||
// Remove the comma of this argument if it's duplication.
|
||||
if (
|
||||
(argNode.properties.length === 0 ||
|
||||
isCommaToken(maybeTrailingComma)) &&
|
||||
isCommaToken(maybeArgumentComma)
|
||||
) {
|
||||
yield fixer.remove(maybeArgumentComma);
|
||||
}
|
||||
} else {
|
||||
// Make spread.
|
||||
if (argNeedsParens(argNode, sourceCode)) {
|
||||
yield fixer.insertTextBefore(left, "...(");
|
||||
yield fixer.insertTextAfter(right, ")");
|
||||
} else {
|
||||
yield fixer.insertTextBefore(left, "...");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow using `Object.assign` with an object literal as the first argument and prefer the use of object spread instead",
|
||||
recommended: false,
|
||||
frozen: true,
|
||||
url: "https://eslint.org/docs/latest/rules/prefer-object-spread",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
fixable: "code",
|
||||
|
||||
messages: {
|
||||
useSpreadMessage:
|
||||
"Use an object spread instead of `Object.assign` eg: `{ ...foo }`.",
|
||||
useLiteralMessage:
|
||||
"Use an object literal instead of `Object.assign`. eg: `{ foo: bar }`.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
const scope = sourceCode.getScope(node);
|
||||
const tracker = new ReferenceTracker(scope);
|
||||
const trackMap = {
|
||||
Object: {
|
||||
assign: { [CALL]: true },
|
||||
},
|
||||
};
|
||||
|
||||
// Iterate all calls of `Object.assign` (only of the global variable `Object`).
|
||||
for (const { node: refNode } of tracker.iterateGlobalReferences(
|
||||
trackMap,
|
||||
)) {
|
||||
if (
|
||||
refNode.arguments.length >= 1 &&
|
||||
refNode.arguments[0].type === "ObjectExpression" &&
|
||||
!hasArraySpread(refNode) &&
|
||||
!(
|
||||
refNode.arguments.length > 1 &&
|
||||
hasArgumentsWithAccessors(refNode)
|
||||
)
|
||||
) {
|
||||
const messageId =
|
||||
refNode.arguments.length === 1
|
||||
? "useLiteralMessage"
|
||||
: "useSpreadMessage";
|
||||
const fix = defineFixer(refNode, sourceCode);
|
||||
|
||||
context.report({ node: refNode, messageId, fix });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import * as core from "../core/index.js";
|
||||
import * as schemas from "./schemas.js";
|
||||
export interface ZodCoercedString<T = unknown> extends schemas._ZodString<core.$ZodStringInternals<T>> {
|
||||
}
|
||||
export declare function string<T = unknown>(params?: string | core.$ZodStringParams): ZodCoercedString<T>;
|
||||
export interface ZodCoercedNumber<T = unknown> extends schemas._ZodNumber<core.$ZodNumberInternals<T>> {
|
||||
}
|
||||
export declare function number<T = unknown>(params?: string | core.$ZodNumberParams): ZodCoercedNumber<T>;
|
||||
export interface ZodCoercedBoolean<T = unknown> extends schemas._ZodBoolean<core.$ZodBooleanInternals<T>> {
|
||||
}
|
||||
export declare function boolean<T = unknown>(params?: string | core.$ZodBooleanParams): ZodCoercedBoolean<T>;
|
||||
export interface ZodCoercedBigInt<T = unknown> extends schemas._ZodBigInt<core.$ZodBigIntInternals<T>> {
|
||||
}
|
||||
export declare function bigint<T = unknown>(params?: string | core.$ZodBigIntParams): ZodCoercedBigInt<T>;
|
||||
export interface ZodCoercedDate<T = unknown> extends schemas._ZodDate<core.$ZodDateInternals<T>> {
|
||||
}
|
||||
export declare function date<T = unknown>(params?: string | core.$ZodDateParams): ZodCoercedDate<T>;
|
||||
@@ -0,0 +1,109 @@
|
||||
import * as util from "../core/util.js";
|
||||
const error = () => {
|
||||
const Sizable = {
|
||||
string: { unit: "stafi", verb: "að hafa" },
|
||||
file: { unit: "bæti", verb: "að hafa" },
|
||||
array: { unit: "hluti", verb: "að hafa" },
|
||||
set: { unit: "hluti", verb: "að hafa" },
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "gildi",
|
||||
email: "netfang",
|
||||
url: "vefslóð",
|
||||
emoji: "emoji",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "ISO dagsetning og tími",
|
||||
date: "ISO dagsetning",
|
||||
time: "ISO tími",
|
||||
duration: "ISO tímalengd",
|
||||
ipv4: "IPv4 address",
|
||||
ipv6: "IPv6 address",
|
||||
cidrv4: "IPv4 range",
|
||||
cidrv6: "IPv6 range",
|
||||
base64: "base64-encoded strengur",
|
||||
base64url: "base64url-encoded strengur",
|
||||
json_string: "JSON strengur",
|
||||
e164: "E.164 tölugildi",
|
||||
jwt: "JWT",
|
||||
template_literal: "gildi",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
number: "númer",
|
||||
array: "fylki",
|
||||
};
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `Rangt gildi: Þú slóst inn ${received} þar sem á að vera instanceof ${issue.expected}`;
|
||||
}
|
||||
return `Rangt gildi: Þú slóst inn ${received} þar sem á að vera ${expected}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Rangt gildi: gert ráð fyrir ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Ógilt val: má vera eitt af eftirfarandi ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Of stórt: gert er ráð fyrir að ${issue.origin ?? "gildi"} hafi ${adj}${issue.maximum.toString()} ${sizing.unit ?? "hluti"}`;
|
||||
return `Of stórt: gert er ráð fyrir að ${issue.origin ?? "gildi"} sé ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Of lítið: gert er ráð fyrir að ${issue.origin} hafi ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `Of lítið: gert er ráð fyrir að ${issue.origin} sé ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with") {
|
||||
return `Ógildur strengur: verður að byrja á "${_issue.prefix}"`;
|
||||
}
|
||||
if (_issue.format === "ends_with")
|
||||
return `Ógildur strengur: verður að enda á "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes")
|
||||
return `Ógildur strengur: verður að innihalda "${_issue.includes}"`;
|
||||
if (_issue.format === "regex")
|
||||
return `Ógildur strengur: verður að fylgja mynstri ${_issue.pattern}`;
|
||||
return `Rangt ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Röng tala: verður að vera margfeldi af ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `Óþekkt ${issue.keys.length > 1 ? "ir lyklar" : "ur lykill"}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Rangur lykill í ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Rangt gildi";
|
||||
case "invalid_element":
|
||||
return `Rangt gildi í ${issue.origin}`;
|
||||
default:
|
||||
return `Rangt gildi`;
|
||||
}
|
||||
};
|
||||
};
|
||||
export default function () {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"moduleKind.js","sourceRoot":"","sources":["../../src/enums/moduleKind.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,MAAM,CAAC,IAAI,UAAe,CAAC;AAC3B,CAAC,UAAU,UAAU;IACjB,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IAC5C,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;IACpD,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IAC1C,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IAC1C,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAChD,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAChD,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAChD,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAChD,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC;IACjD,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;IAClD,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;IAClD,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;IAClD,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;IACtD,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;AAC1D,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC"}
|
||||
@@ -0,0 +1,467 @@
|
||||
/**
|
||||
* ed25519 Twisted Edwards curve with following addons:
|
||||
* - X25519 ECDH
|
||||
* - Ristretto cofactor elimination
|
||||
* - Elligator hash-to-group / point indistinguishability
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { sha512 } from '@noble/hashes/sha2.js';
|
||||
import { abytes, concatBytes, utf8ToBytes } from '@noble/hashes/utils.js';
|
||||
import { pippenger } from "./abstract/curve.js";
|
||||
import { PrimeEdwardsPoint, twistedEdwards, } from "./abstract/edwards.js";
|
||||
import { _DST_scalar, createHasher, expand_message_xmd, } from "./abstract/hash-to-curve.js";
|
||||
import { Field, FpInvertBatch, FpSqrtEven, isNegativeLE, mod, pow2, } from "./abstract/modular.js";
|
||||
import { montgomery } from "./abstract/montgomery.js";
|
||||
import { bytesToNumberLE, ensureBytes, equalBytes } from "./utils.js";
|
||||
// prettier-ignore
|
||||
const _0n = /* @__PURE__ */ BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
||||
// prettier-ignore
|
||||
const _5n = BigInt(5), _8n = BigInt(8);
|
||||
// P = 2n**255n-19n
|
||||
const ed25519_CURVE_p = BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed');
|
||||
// N = 2n**252n + 27742317777372353535851937790883648493n
|
||||
// a = Fp.create(BigInt(-1))
|
||||
// d = -121665/121666 a.k.a. Fp.neg(121665 * Fp.inv(121666))
|
||||
const ed25519_CURVE = /* @__PURE__ */ (() => ({
|
||||
p: ed25519_CURVE_p,
|
||||
n: BigInt('0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed'),
|
||||
h: _8n,
|
||||
a: BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec'),
|
||||
d: BigInt('0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3'),
|
||||
Gx: BigInt('0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a'),
|
||||
Gy: BigInt('0x6666666666666666666666666666666666666666666666666666666666666658'),
|
||||
}))();
|
||||
function ed25519_pow_2_252_3(x) {
|
||||
// prettier-ignore
|
||||
const _10n = BigInt(10), _20n = BigInt(20), _40n = BigInt(40), _80n = BigInt(80);
|
||||
const P = ed25519_CURVE_p;
|
||||
const x2 = (x * x) % P;
|
||||
const b2 = (x2 * x) % P; // x^3, 11
|
||||
const b4 = (pow2(b2, _2n, P) * b2) % P; // x^15, 1111
|
||||
const b5 = (pow2(b4, _1n, P) * x) % P; // x^31
|
||||
const b10 = (pow2(b5, _5n, P) * b5) % P;
|
||||
const b20 = (pow2(b10, _10n, P) * b10) % P;
|
||||
const b40 = (pow2(b20, _20n, P) * b20) % P;
|
||||
const b80 = (pow2(b40, _40n, P) * b40) % P;
|
||||
const b160 = (pow2(b80, _80n, P) * b80) % P;
|
||||
const b240 = (pow2(b160, _80n, P) * b80) % P;
|
||||
const b250 = (pow2(b240, _10n, P) * b10) % P;
|
||||
const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P;
|
||||
// ^ To pow to (p+3)/8, multiply it by x.
|
||||
return { pow_p_5_8, b2 };
|
||||
}
|
||||
function adjustScalarBytes(bytes) {
|
||||
// Section 5: For X25519, in order to decode 32 random bytes as an integer scalar,
|
||||
// set the three least significant bits of the first byte
|
||||
bytes[0] &= 248; // 0b1111_1000
|
||||
// and the most significant bit of the last to zero,
|
||||
bytes[31] &= 127; // 0b0111_1111
|
||||
// set the second most significant bit of the last byte to 1
|
||||
bytes[31] |= 64; // 0b0100_0000
|
||||
return bytes;
|
||||
}
|
||||
// √(-1) aka √(a) aka 2^((p-1)/4)
|
||||
// Fp.sqrt(Fp.neg(1))
|
||||
const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt('19681161376707505956807079304988542015446066515923890162744021073123829784752');
|
||||
// sqrt(u/v)
|
||||
function uvRatio(u, v) {
|
||||
const P = ed25519_CURVE_p;
|
||||
const v3 = mod(v * v * v, P); // v³
|
||||
const v7 = mod(v3 * v3 * v, P); // v⁷
|
||||
// (p+3)/8 and (p-5)/8
|
||||
const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
|
||||
let x = mod(u * v3 * pow, P); // (uv³)(uv⁷)^(p-5)/8
|
||||
const vx2 = mod(v * x * x, P); // vx²
|
||||
const root1 = x; // First root candidate
|
||||
const root2 = mod(x * ED25519_SQRT_M1, P); // Second root candidate
|
||||
const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root
|
||||
const useRoot2 = vx2 === mod(-u, P); // If vx² = -u, set x <-- x * 2^((p-1)/4)
|
||||
const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P); // There is no valid root, vx² = -u√(-1)
|
||||
if (useRoot1)
|
||||
x = root1;
|
||||
if (useRoot2 || noRoot)
|
||||
x = root2; // We return root2 anyway, for const-time
|
||||
if (isNegativeLE(x, P))
|
||||
x = mod(-x, P);
|
||||
return { isValid: useRoot1 || useRoot2, value: x };
|
||||
}
|
||||
const Fp = /* @__PURE__ */ (() => Field(ed25519_CURVE.p, { isLE: true }))();
|
||||
const Fn = /* @__PURE__ */ (() => Field(ed25519_CURVE.n, { isLE: true }))();
|
||||
const ed25519Defaults = /* @__PURE__ */ (() => ({
|
||||
...ed25519_CURVE,
|
||||
Fp,
|
||||
hash: sha512,
|
||||
adjustScalarBytes,
|
||||
// dom2
|
||||
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
|
||||
// Constant-time, u/√v
|
||||
uvRatio,
|
||||
}))();
|
||||
/**
|
||||
* ed25519 curve with EdDSA signatures.
|
||||
* @example
|
||||
* import { ed25519 } from '@noble/curves/ed25519';
|
||||
* const { secretKey, publicKey } = ed25519.keygen();
|
||||
* const msg = new TextEncoder().encode('hello');
|
||||
* const sig = ed25519.sign(msg, priv);
|
||||
* ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
|
||||
* ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5
|
||||
*/
|
||||
export const ed25519 = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))();
|
||||
function ed25519_domain(data, ctx, phflag) {
|
||||
if (ctx.length > 255)
|
||||
throw new Error('Context is too big');
|
||||
return concatBytes(utf8ToBytes('SigEd25519 no Ed25519 collisions'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
|
||||
}
|
||||
/** Context of ed25519. Uses context for domain separation. */
|
||||
export const ed25519ctx = /* @__PURE__ */ (() => twistedEdwards({
|
||||
...ed25519Defaults,
|
||||
domain: ed25519_domain,
|
||||
}))();
|
||||
/** Prehashed version of ed25519. Accepts already-hashed messages in sign() and verify(). */
|
||||
export const ed25519ph = /* @__PURE__ */ (() => twistedEdwards(Object.assign({}, ed25519Defaults, {
|
||||
domain: ed25519_domain,
|
||||
prehash: sha512,
|
||||
})))();
|
||||
/**
|
||||
* ECDH using curve25519 aka x25519.
|
||||
* @example
|
||||
* import { x25519 } from '@noble/curves/ed25519';
|
||||
* const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4';
|
||||
* const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c';
|
||||
* x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases
|
||||
* x25519.getPublicKey(priv) === x25519.scalarMultBase(priv);
|
||||
* x25519.getPublicKey(x25519.utils.randomSecretKey());
|
||||
*/
|
||||
export const x25519 = /* @__PURE__ */ (() => {
|
||||
const P = Fp.ORDER;
|
||||
return montgomery({
|
||||
P,
|
||||
type: 'x25519',
|
||||
powPminus2: (x) => {
|
||||
// x^(p-2) aka x^(2^255-21)
|
||||
const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x);
|
||||
return mod(pow2(pow_p_5_8, _3n, P) * b2, P);
|
||||
},
|
||||
adjustScalarBytes,
|
||||
});
|
||||
})();
|
||||
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
|
||||
// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
|
||||
// SageMath returns different root first and everything falls apart
|
||||
const ELL2_C1 = /* @__PURE__ */ (() => (ed25519_CURVE_p + _3n) / _8n)(); // 1. c1 = (q + 3) / 8 # Integer arithmetic
|
||||
const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))(); // 2. c2 = 2^c1
|
||||
const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))(); // 3. c3 = sqrt(-1)
|
||||
// prettier-ignore
|
||||
function map_to_curve_elligator2_curve25519(u) {
|
||||
const ELL2_C4 = (ed25519_CURVE_p - _5n) / _8n; // 4. c4 = (q - 5) / 8 # Integer arithmetic
|
||||
const ELL2_J = BigInt(486662);
|
||||
let tv1 = Fp.sqr(u); // 1. tv1 = u^2
|
||||
tv1 = Fp.mul(tv1, _2n); // 2. tv1 = 2 * tv1
|
||||
let xd = Fp.add(tv1, Fp.ONE); // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not
|
||||
let x1n = Fp.neg(ELL2_J); // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2)
|
||||
let tv2 = Fp.sqr(xd); // 5. tv2 = xd^2
|
||||
let gxd = Fp.mul(tv2, xd); // 6. gxd = tv2 * xd # gxd = xd^3
|
||||
let gx1 = Fp.mul(tv1, ELL2_J); // 7. gx1 = J * tv1 # x1n + J * xd
|
||||
gx1 = Fp.mul(gx1, x1n); // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
|
||||
gx1 = Fp.add(gx1, tv2); // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
|
||||
gx1 = Fp.mul(gx1, x1n); // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
|
||||
let tv3 = Fp.sqr(gxd); // 11. tv3 = gxd^2
|
||||
tv2 = Fp.sqr(tv3); // 12. tv2 = tv3^2 # gxd^4
|
||||
tv3 = Fp.mul(tv3, gxd); // 13. tv3 = tv3 * gxd # gxd^3
|
||||
tv3 = Fp.mul(tv3, gx1); // 14. tv3 = tv3 * gx1 # gx1 * gxd^3
|
||||
tv2 = Fp.mul(tv2, tv3); // 15. tv2 = tv2 * tv3 # gx1 * gxd^7
|
||||
let y11 = Fp.pow(tv2, ELL2_C4); // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8)
|
||||
y11 = Fp.mul(y11, tv3); // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8)
|
||||
let y12 = Fp.mul(y11, ELL2_C3); // 18. y12 = y11 * c3
|
||||
tv2 = Fp.sqr(y11); // 19. tv2 = y11^2
|
||||
tv2 = Fp.mul(tv2, gxd); // 20. tv2 = tv2 * gxd
|
||||
let e1 = Fp.eql(tv2, gx1); // 21. e1 = tv2 == gx1
|
||||
let y1 = Fp.cmov(y12, y11, e1); // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt
|
||||
let x2n = Fp.mul(x1n, tv1); // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd
|
||||
let y21 = Fp.mul(y11, u); // 24. y21 = y11 * u
|
||||
y21 = Fp.mul(y21, ELL2_C2); // 25. y21 = y21 * c2
|
||||
let y22 = Fp.mul(y21, ELL2_C3); // 26. y22 = y21 * c3
|
||||
let gx2 = Fp.mul(gx1, tv1); // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1)
|
||||
tv2 = Fp.sqr(y21); // 28. tv2 = y21^2
|
||||
tv2 = Fp.mul(tv2, gxd); // 29. tv2 = tv2 * gxd
|
||||
let e2 = Fp.eql(tv2, gx2); // 30. e2 = tv2 == gx2
|
||||
let y2 = Fp.cmov(y22, y21, e2); // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt
|
||||
tv2 = Fp.sqr(y1); // 32. tv2 = y1^2
|
||||
tv2 = Fp.mul(tv2, gxd); // 33. tv2 = tv2 * gxd
|
||||
let e3 = Fp.eql(tv2, gx1); // 34. e3 = tv2 == gx1
|
||||
let xn = Fp.cmov(x2n, x1n, e3); // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2
|
||||
let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2
|
||||
let e4 = Fp.isOdd(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y
|
||||
y = Fp.cmov(y, Fp.neg(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
|
||||
return { xMn: xn, xMd: xd, yMn: y, yMd: _1n }; // 39. return (xn, xd, y, 1)
|
||||
}
|
||||
const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))(); // sgn0(c1) MUST equal 0
|
||||
function map_to_curve_elligator2_edwards25519(u) {
|
||||
const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) =
|
||||
// map_to_curve_elligator2_curve25519(u)
|
||||
let xn = Fp.mul(xMn, yMd); // 2. xn = xMn * yMd
|
||||
xn = Fp.mul(xn, ELL2_C1_EDWARDS); // 3. xn = xn * c1
|
||||
let xd = Fp.mul(xMd, yMn); // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM
|
||||
let yn = Fp.sub(xMn, xMd); // 5. yn = xMn - xMd
|
||||
let yd = Fp.add(xMn, xMd); // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d)
|
||||
let tv1 = Fp.mul(xd, yd); // 7. tv1 = xd * yd
|
||||
let e = Fp.eql(tv1, Fp.ZERO); // 8. e = tv1 == 0
|
||||
xn = Fp.cmov(xn, Fp.ZERO, e); // 9. xn = CMOV(xn, 0, e)
|
||||
xd = Fp.cmov(xd, Fp.ONE, e); // 10. xd = CMOV(xd, 1, e)
|
||||
yn = Fp.cmov(yn, Fp.ONE, e); // 11. yn = CMOV(yn, 1, e)
|
||||
yd = Fp.cmov(yd, Fp.ONE, e); // 12. yd = CMOV(yd, 1, e)
|
||||
const [xd_inv, yd_inv] = FpInvertBatch(Fp, [xd, yd], true); // batch division
|
||||
return { x: Fp.mul(xn, xd_inv), y: Fp.mul(yn, yd_inv) }; // 13. return (xn, xd, yn, yd)
|
||||
}
|
||||
/** Hashing to ed25519 points / field. RFC 9380 methods. */
|
||||
export const ed25519_hasher = /* @__PURE__ */ (() => createHasher(ed25519.Point, (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]), {
|
||||
DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
|
||||
encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_',
|
||||
p: ed25519_CURVE_p,
|
||||
m: 1,
|
||||
k: 128,
|
||||
expand: 'xmd',
|
||||
hash: sha512,
|
||||
}))();
|
||||
// √(-1) aka √(a) aka 2^((p-1)/4)
|
||||
const SQRT_M1 = ED25519_SQRT_M1;
|
||||
// √(ad - 1)
|
||||
const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt('25063068953384623474111414158702152701244531502492656460079210482610430750235');
|
||||
// 1 / √(a-d)
|
||||
const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt('54469307008909316920995813868745141605393597292927456921205312896311721017578');
|
||||
// 1-d²
|
||||
const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt('1159843021668779879193775521855586647937357759715417654439879720876111806838');
|
||||
// (d-1)²
|
||||
const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt('40440834346308536858101042469323190826248399146238708352240133220865137265952');
|
||||
// Calculates 1/√(number)
|
||||
const invertSqrt = (number) => uvRatio(_1n, number);
|
||||
const MAX_255B = /* @__PURE__ */ BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
|
||||
const bytes255ToNumberLE = (bytes) => ed25519.Point.Fp.create(bytesToNumberLE(bytes) & MAX_255B);
|
||||
/**
|
||||
* Computes Elligator map for Ristretto255.
|
||||
* Described in [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#appendix-B) and on
|
||||
* the [website](https://ristretto.group/formulas/elligator.html).
|
||||
*/
|
||||
function calcElligatorRistrettoMap(r0) {
|
||||
const { d } = ed25519_CURVE;
|
||||
const P = ed25519_CURVE_p;
|
||||
const mod = (n) => Fp.create(n);
|
||||
const r = mod(SQRT_M1 * r0 * r0); // 1
|
||||
const Ns = mod((r + _1n) * ONE_MINUS_D_SQ); // 2
|
||||
let c = BigInt(-1); // 3
|
||||
const D = mod((c - d * r) * mod(r + d)); // 4
|
||||
let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D); // 5
|
||||
let s_ = mod(s * r0); // 6
|
||||
if (!isNegativeLE(s_, P))
|
||||
s_ = mod(-s_);
|
||||
if (!Ns_D_is_sq)
|
||||
s = s_; // 7
|
||||
if (!Ns_D_is_sq)
|
||||
c = r; // 8
|
||||
const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D); // 9
|
||||
const s2 = s * s;
|
||||
const W0 = mod((s + s) * D); // 10
|
||||
const W1 = mod(Nt * SQRT_AD_MINUS_ONE); // 11
|
||||
const W2 = mod(_1n - s2); // 12
|
||||
const W3 = mod(_1n + s2); // 13
|
||||
return new ed25519.Point(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2));
|
||||
}
|
||||
function ristretto255_map(bytes) {
|
||||
abytes(bytes, 64);
|
||||
const r1 = bytes255ToNumberLE(bytes.subarray(0, 32));
|
||||
const R1 = calcElligatorRistrettoMap(r1);
|
||||
const r2 = bytes255ToNumberLE(bytes.subarray(32, 64));
|
||||
const R2 = calcElligatorRistrettoMap(r2);
|
||||
return new _RistrettoPoint(R1.add(R2));
|
||||
}
|
||||
/**
|
||||
* Wrapper over Edwards Point for ristretto255.
|
||||
*
|
||||
* Each ed25519/ExtendedPoint has 8 different equivalent points. This can be
|
||||
* a source of bugs for protocols like ring signatures. Ristretto was created to solve this.
|
||||
* Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint,
|
||||
* but it should work in its own namespace: do not combine those two.
|
||||
* See [RFC9496](https://www.rfc-editor.org/rfc/rfc9496).
|
||||
*/
|
||||
class _RistrettoPoint extends PrimeEdwardsPoint {
|
||||
constructor(ep) {
|
||||
super(ep);
|
||||
}
|
||||
static fromAffine(ap) {
|
||||
return new _RistrettoPoint(ed25519.Point.fromAffine(ap));
|
||||
}
|
||||
assertSame(other) {
|
||||
if (!(other instanceof _RistrettoPoint))
|
||||
throw new Error('RistrettoPoint expected');
|
||||
}
|
||||
init(ep) {
|
||||
return new _RistrettoPoint(ep);
|
||||
}
|
||||
/** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
|
||||
static hashToCurve(hex) {
|
||||
return ristretto255_map(ensureBytes('ristrettoHash', hex, 64));
|
||||
}
|
||||
static fromBytes(bytes) {
|
||||
abytes(bytes, 32);
|
||||
const { a, d } = ed25519_CURVE;
|
||||
const P = ed25519_CURVE_p;
|
||||
const mod = (n) => Fp.create(n);
|
||||
const s = bytes255ToNumberLE(bytes);
|
||||
// 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
|
||||
// 3. Check that s is non-negative, or else abort
|
||||
if (!equalBytes(Fp.toBytes(s), bytes) || isNegativeLE(s, P))
|
||||
throw new Error('invalid ristretto255 encoding 1');
|
||||
const s2 = mod(s * s);
|
||||
const u1 = mod(_1n + a * s2); // 4 (a is -1)
|
||||
const u2 = mod(_1n - a * s2); // 5
|
||||
const u1_2 = mod(u1 * u1);
|
||||
const u2_2 = mod(u2 * u2);
|
||||
const v = mod(a * d * u1_2 - u2_2); // 6
|
||||
const { isValid, value: I } = invertSqrt(mod(v * u2_2)); // 7
|
||||
const Dx = mod(I * u2); // 8
|
||||
const Dy = mod(I * Dx * v); // 9
|
||||
let x = mod((s + s) * Dx); // 10
|
||||
if (isNegativeLE(x, P))
|
||||
x = mod(-x); // 10
|
||||
const y = mod(u1 * Dy); // 11
|
||||
const t = mod(x * y); // 12
|
||||
if (!isValid || isNegativeLE(t, P) || y === _0n)
|
||||
throw new Error('invalid ristretto255 encoding 2');
|
||||
return new _RistrettoPoint(new ed25519.Point(x, y, _1n, t));
|
||||
}
|
||||
/**
|
||||
* Converts ristretto-encoded string to ristretto point.
|
||||
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-decode).
|
||||
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
||||
*/
|
||||
static fromHex(hex) {
|
||||
return _RistrettoPoint.fromBytes(ensureBytes('ristrettoHex', hex, 32));
|
||||
}
|
||||
static msm(points, scalars) {
|
||||
return pippenger(_RistrettoPoint, ed25519.Point.Fn, points, scalars);
|
||||
}
|
||||
/**
|
||||
* Encodes ristretto point to Uint8Array.
|
||||
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-encode).
|
||||
*/
|
||||
toBytes() {
|
||||
let { X, Y, Z, T } = this.ep;
|
||||
const P = ed25519_CURVE_p;
|
||||
const mod = (n) => Fp.create(n);
|
||||
const u1 = mod(mod(Z + Y) * mod(Z - Y)); // 1
|
||||
const u2 = mod(X * Y); // 2
|
||||
// Square root always exists
|
||||
const u2sq = mod(u2 * u2);
|
||||
const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)); // 3
|
||||
const D1 = mod(invsqrt * u1); // 4
|
||||
const D2 = mod(invsqrt * u2); // 5
|
||||
const zInv = mod(D1 * D2 * T); // 6
|
||||
let D; // 7
|
||||
if (isNegativeLE(T * zInv, P)) {
|
||||
let _x = mod(Y * SQRT_M1);
|
||||
let _y = mod(X * SQRT_M1);
|
||||
X = _x;
|
||||
Y = _y;
|
||||
D = mod(D1 * INVSQRT_A_MINUS_D);
|
||||
}
|
||||
else {
|
||||
D = D2; // 8
|
||||
}
|
||||
if (isNegativeLE(X * zInv, P))
|
||||
Y = mod(-Y); // 9
|
||||
let s = mod((Z - Y) * D); // 10 (check footer's note, no sqrt(-a))
|
||||
if (isNegativeLE(s, P))
|
||||
s = mod(-s);
|
||||
return Fp.toBytes(s); // 11
|
||||
}
|
||||
/**
|
||||
* Compares two Ristretto points.
|
||||
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-equals).
|
||||
*/
|
||||
equals(other) {
|
||||
this.assertSame(other);
|
||||
const { X: X1, Y: Y1 } = this.ep;
|
||||
const { X: X2, Y: Y2 } = other.ep;
|
||||
const mod = (n) => Fp.create(n);
|
||||
// (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
|
||||
const one = mod(X1 * Y2) === mod(Y1 * X2);
|
||||
const two = mod(Y1 * Y2) === mod(X1 * X2);
|
||||
return one || two;
|
||||
}
|
||||
is0() {
|
||||
return this.equals(_RistrettoPoint.ZERO);
|
||||
}
|
||||
}
|
||||
// Do NOT change syntax: the following gymnastics is done,
|
||||
// because typescript strips comments, which makes bundlers disable tree-shaking.
|
||||
// prettier-ignore
|
||||
_RistrettoPoint.BASE =
|
||||
/* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.BASE))();
|
||||
// prettier-ignore
|
||||
_RistrettoPoint.ZERO =
|
||||
/* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.ZERO))();
|
||||
// prettier-ignore
|
||||
_RistrettoPoint.Fp =
|
||||
/* @__PURE__ */ (() => Fp)();
|
||||
// prettier-ignore
|
||||
_RistrettoPoint.Fn =
|
||||
/* @__PURE__ */ (() => Fn)();
|
||||
export const ristretto255 = { Point: _RistrettoPoint };
|
||||
/** Hashing to ristretto255 points / field. RFC 9380 methods. */
|
||||
export const ristretto255_hasher = {
|
||||
hashToCurve(msg, options) {
|
||||
const DST = options?.DST || 'ristretto255_XMD:SHA-512_R255MAP_RO_';
|
||||
const xmd = expand_message_xmd(msg, DST, 64, sha512);
|
||||
return ristretto255_map(xmd);
|
||||
},
|
||||
hashToScalar(msg, options = { DST: _DST_scalar }) {
|
||||
const xmd = expand_message_xmd(msg, options.DST, 64, sha512);
|
||||
return Fn.create(bytesToNumberLE(xmd));
|
||||
},
|
||||
};
|
||||
// export const ristretto255_oprf: OPRF = createORPF({
|
||||
// name: 'ristretto255-SHA512',
|
||||
// Point: RistrettoPoint,
|
||||
// hash: sha512,
|
||||
// hashToGroup: ristretto255_hasher.hashToCurve,
|
||||
// hashToScalar: ristretto255_hasher.hashToScalar,
|
||||
// });
|
||||
/**
|
||||
* Weird / bogus points, useful for debugging.
|
||||
* All 8 ed25519 points of 8-torsion subgroup can be generated from the point
|
||||
* T = `26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05`.
|
||||
* ⟨T⟩ = { O, T, 2T, 3T, 4T, 5T, 6T, 7T }
|
||||
*/
|
||||
export const ED25519_TORSION_SUBGROUP = [
|
||||
'0100000000000000000000000000000000000000000000000000000000000000',
|
||||
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a',
|
||||
'0000000000000000000000000000000000000000000000000000000000000080',
|
||||
'26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05',
|
||||
'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
|
||||
'26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85',
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa',
|
||||
];
|
||||
/** @deprecated use `ed25519.utils.toMontgomery` */
|
||||
export function edwardsToMontgomeryPub(edwardsPub) {
|
||||
return ed25519.utils.toMontgomery(ensureBytes('pub', edwardsPub));
|
||||
}
|
||||
/** @deprecated use `ed25519.utils.toMontgomery` */
|
||||
export const edwardsToMontgomery = edwardsToMontgomeryPub;
|
||||
/** @deprecated use `ed25519.utils.toMontgomerySecret` */
|
||||
export function edwardsToMontgomeryPriv(edwardsPriv) {
|
||||
return ed25519.utils.toMontgomerySecret(ensureBytes('pub', edwardsPriv));
|
||||
}
|
||||
/** @deprecated use `ristretto255.Point` */
|
||||
export const RistrettoPoint = _RistrettoPoint;
|
||||
/** @deprecated use `import { ed25519_hasher } from '@noble/curves/ed25519.js';` */
|
||||
export const hashToCurve = /* @__PURE__ */ (() => ed25519_hasher.hashToCurve)();
|
||||
/** @deprecated use `import { ed25519_hasher } from '@noble/curves/ed25519.js';` */
|
||||
export const encodeToCurve = /* @__PURE__ */ (() => ed25519_hasher.encodeToCurve)();
|
||||
/** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
|
||||
export const hashToRistretto255 = /* @__PURE__ */ (() => ristretto255_hasher.hashToCurve)();
|
||||
/** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
|
||||
export const hash_to_ristretto255 = /* @__PURE__ */ (() => ristretto255_hasher.hashToCurve)();
|
||||
//# sourceMappingURL=ed25519.js.map
|
||||
@@ -0,0 +1,7 @@
|
||||
# @vitest/utils
|
||||
|
||||
[](https://npmx.dev/package/@vitest/utils)
|
||||
|
||||
Internal shared utilities used by other Vitest packages.
|
||||
|
||||
[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/utils) | [Documentation](https://vitest.dev/)
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const es2019_object: LibDefinition;
|
||||
@@ -0,0 +1,470 @@
|
||||
"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 () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.checkSyntaxError = checkSyntaxError;
|
||||
const ts = __importStar(require("typescript"));
|
||||
const check_modifiers_1 = require("./check-modifiers");
|
||||
const getImportClausePhaseModifier_1 = require("./getImportClausePhaseModifier");
|
||||
const node_utils_1 = require("./node-utils");
|
||||
const SyntaxKind = ts.SyntaxKind;
|
||||
function checkSyntaxError(tsNode, parent, allowPattern) {
|
||||
(0, check_modifiers_1.checkModifiers)(tsNode);
|
||||
const node = tsNode;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SwitchStatement:
|
||||
if (node.caseBlock.clauses.filter(switchCase => switchCase.kind === SyntaxKind.DefaultClause).length > 1) {
|
||||
throw (0, node_utils_1.createError)(node, "A 'default' clause cannot appear more than once in a 'switch' statement.");
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ThrowStatement:
|
||||
if (node.expression.end === node.expression.pos) {
|
||||
throw (0, node_utils_1.createError)(node, 'A throw statement must throw an expression.');
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.CatchClause:
|
||||
if (node.variableDeclaration?.initializer) {
|
||||
throw (0, node_utils_1.createError)(node.variableDeclaration.initializer, 'Catch clause variable cannot have an initializer.');
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.FunctionDeclaration: {
|
||||
const isDeclare = (0, node_utils_1.hasModifier)(SyntaxKind.DeclareKeyword, node);
|
||||
const isAsync = (0, node_utils_1.hasModifier)(SyntaxKind.AsyncKeyword, node);
|
||||
const isGenerator = !!node.asteriskToken;
|
||||
if (isDeclare) {
|
||||
if (node.body) {
|
||||
throw (0, node_utils_1.createError)(node, 'An implementation cannot be declared in ambient contexts.');
|
||||
}
|
||||
else if (isAsync) {
|
||||
throw (0, node_utils_1.createError)(node, "'async' modifier cannot be used in an ambient context.");
|
||||
}
|
||||
else if (isGenerator) {
|
||||
throw (0, node_utils_1.createError)(node, 'Generators are not allowed in an ambient context.');
|
||||
}
|
||||
}
|
||||
else if (!node.body && isGenerator) {
|
||||
throw (0, node_utils_1.createError)(node, 'A function signature cannot be declared as a generator.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.VariableDeclaration: {
|
||||
const hasExclamationToken = !!node.exclamationToken;
|
||||
if (hasExclamationToken) {
|
||||
if (node.initializer) {
|
||||
throw (0, node_utils_1.createError)(node, 'Declarations with initializers cannot also have definite assignment assertions.');
|
||||
}
|
||||
else if (node.name.kind !== SyntaxKind.Identifier || !node.type) {
|
||||
throw (0, node_utils_1.createError)(node, 'Declarations with definite assignment assertions must also have type annotations.');
|
||||
}
|
||||
}
|
||||
if (node.parent.kind === SyntaxKind.VariableDeclarationList) {
|
||||
const variableDeclarationList = node.parent;
|
||||
const kind = (0, node_utils_1.getDeclarationKind)(variableDeclarationList);
|
||||
if (kind === 'using' || kind === 'await using') {
|
||||
if (variableDeclarationList.parent.kind === SyntaxKind.ForInStatement) {
|
||||
throw (0, node_utils_1.createError)(variableDeclarationList, `The left-hand side of a 'for...in' statement cannot be a '${kind}' declaration.`);
|
||||
}
|
||||
if (variableDeclarationList.parent.kind === SyntaxKind.ForStatement ||
|
||||
variableDeclarationList.parent.kind === SyntaxKind.VariableStatement) {
|
||||
if (!node.initializer) {
|
||||
throw (0, node_utils_1.createError)(node, `'${kind}' declarations must be initialized.`);
|
||||
}
|
||||
if (node.name.kind !== SyntaxKind.Identifier) {
|
||||
throw (0, node_utils_1.createError)(node.name, `'${kind}' declarations may not have binding patterns.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (variableDeclarationList.parent.kind === SyntaxKind.VariableStatement) {
|
||||
const variableStatement = variableDeclarationList.parent;
|
||||
const hasDeclareKeyword = (0, node_utils_1.hasModifier)(SyntaxKind.DeclareKeyword, variableStatement);
|
||||
// Definite assignment only allowed for non-declare let and var
|
||||
if ((hasDeclareKeyword ||
|
||||
['await using', 'const', 'using'].includes(kind)) &&
|
||||
hasExclamationToken) {
|
||||
throw (0, node_utils_1.createError)(node, `A definite assignment assertion '!' is not permitted in this context.`);
|
||||
}
|
||||
if (hasDeclareKeyword &&
|
||||
node.initializer &&
|
||||
(['let', 'var'].includes(kind) || node.type)) {
|
||||
throw (0, node_utils_1.createError)(node, `Initializers are not permitted in ambient contexts.`);
|
||||
}
|
||||
// Theoretically, only certain initializers are allowed for declare const,
|
||||
// (TS1254: A 'const' initializer in an ambient context must be a string
|
||||
// or numeric literal or literal enum reference.) but we just allow
|
||||
// all expressions
|
||||
// Note! No-declare does not mean the variable is not ambient, because
|
||||
// it can be further nested in other declare contexts. Therefore we cannot
|
||||
// check for const initializers.
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.VariableStatement: {
|
||||
const declarations = node.declarationList.declarations;
|
||||
if (!declarations.length) {
|
||||
throw (0, node_utils_1.createError)(node, 'A variable declaration list must have at least one variable declarator.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.PropertyAssignment: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
||||
const { exclamationToken, questionToken } = node;
|
||||
if (questionToken) {
|
||||
throw (0, node_utils_1.createError)(questionToken, 'A property assignment cannot have a question token.');
|
||||
}
|
||||
if (exclamationToken) {
|
||||
throw (0, node_utils_1.createError)(exclamationToken, 'A property assignment cannot have an exclamation token.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ShorthandPropertyAssignment: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
||||
const { exclamationToken, modifiers, questionToken } = node;
|
||||
if (modifiers) {
|
||||
throw (0, node_utils_1.createError)(modifiers[0], 'A shorthand property assignment cannot have modifiers.');
|
||||
}
|
||||
if (questionToken) {
|
||||
throw (0, node_utils_1.createError)(questionToken, 'A shorthand property assignment cannot have a question token.');
|
||||
}
|
||||
if (exclamationToken) {
|
||||
throw (0, node_utils_1.createError)(exclamationToken, 'A shorthand property assignment cannot have an exclamation token.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.PropertyDeclaration: {
|
||||
const isAbstract = (0, node_utils_1.hasModifier)(SyntaxKind.AbstractKeyword, node);
|
||||
if (isAbstract && node.initializer) {
|
||||
throw (0, node_utils_1.createError)(node.initializer, `Abstract property cannot have an initializer.`);
|
||||
}
|
||||
const isDefinite = !!node.exclamationToken;
|
||||
if (isDefinite && isAbstract) {
|
||||
throw (0, node_utils_1.createError)(node.exclamationToken, `A definite assignment assertion '!' is not permitted in this context.`);
|
||||
}
|
||||
if (isDefinite && !node.type) {
|
||||
throw (0, node_utils_1.createError)(node, `Declarations with definite assignment assertions must also have type annotations.`);
|
||||
}
|
||||
if (isDefinite && node.initializer) {
|
||||
throw (0, node_utils_1.createError)(node, `Declarations with initializers cannot also have definite assignment assertions.`);
|
||||
}
|
||||
if (node.name.kind === SyntaxKind.StringLiteral &&
|
||||
node.name.text === 'constructor') {
|
||||
throw (0, node_utils_1.createError)(node.name, "Classes may not have a field named 'constructor'.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
if (node.tag.flags & ts.NodeFlags.OptionalChain) {
|
||||
throw (0, node_utils_1.createError)(node, 'Tagged template expressions are not permitted in an optional chain.');
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.BinaryExpression:
|
||||
if (node.operatorToken.kind !== SyntaxKind.InKeyword &&
|
||||
node.left.kind === SyntaxKind.PrivateIdentifier) {
|
||||
throw (0, node_utils_1.createError)(node.left, "Private identifiers cannot appear on the right-hand-side of an 'in' expression.");
|
||||
}
|
||||
else if (node.right.kind === SyntaxKind.PrivateIdentifier) {
|
||||
throw (0, node_utils_1.createError)(node.right, "Private identifiers are only allowed on the left-hand-side of an 'in' expression.");
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.MappedType:
|
||||
if (node.members && node.members.length > 0) {
|
||||
throw (0, node_utils_1.createError)(node.members[0], 'A mapped type may not declare properties or methods.');
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.PropertySignature: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
||||
const { initializer } = node;
|
||||
if (initializer) {
|
||||
throw (0, node_utils_1.createError)(initializer, 'A property signature cannot have an initializer.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.FunctionType: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
||||
const { modifiers } = node;
|
||||
if (modifiers) {
|
||||
throw (0, node_utils_1.createError)(modifiers[0], 'A function type cannot have modifiers.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.EnumMember: {
|
||||
const computed = node.name.kind === ts.SyntaxKind.ComputedPropertyName;
|
||||
if (computed) {
|
||||
throw (0, node_utils_1.createError)(node.name, 'Computed property names are not allowed in enums.');
|
||||
}
|
||||
if (node.name.kind === SyntaxKind.NumericLiteral ||
|
||||
node.name.kind === SyntaxKind.BigIntLiteral) {
|
||||
throw (0, node_utils_1.createError)(node.name, 'An enum member cannot have a numeric name.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ExternalModuleReference:
|
||||
if (node.expression.kind !== SyntaxKind.StringLiteral) {
|
||||
throw (0, node_utils_1.createError)(node.expression, 'String literal expected.');
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.PostfixUnaryExpression: {
|
||||
const operator = (0, node_utils_1.getTextForTokenKind)(node.operator);
|
||||
/**
|
||||
* ESTree uses UpdateExpression for ++/--
|
||||
*/
|
||||
if ((operator === '++' || operator === '--') &&
|
||||
!(0, node_utils_1.isValidAssignmentTarget)(node.operand)) {
|
||||
throw (0, node_utils_1.createError)(node.operand, 'Invalid left-hand side expression in unary operation');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ImportDeclaration: {
|
||||
const { importClause } = node;
|
||||
const importPhase = (0, getImportClausePhaseModifier_1.getImportClausePhaseModifier)(importClause);
|
||||
if (importPhase === 'type' &&
|
||||
importClause?.name &&
|
||||
importClause.namedBindings) {
|
||||
throw (0, node_utils_1.createError)(importClause, 'A type-only import can specify a default import or named bindings, but not both.');
|
||||
}
|
||||
const isNamedImport = importClause?.namedBindings?.kind === SyntaxKind.NamedImports;
|
||||
const isDefaultImport = !!importClause?.name;
|
||||
if (importPhase === 'defer' && isNamedImport) {
|
||||
throw (0, node_utils_1.createError)(importClause, 'Named imports are not allowed in a deferred import.');
|
||||
}
|
||||
if (importPhase === 'defer' && isDefaultImport) {
|
||||
throw (0, node_utils_1.createError)(importClause, 'Default imports are not allowed in a deferred import.');
|
||||
}
|
||||
assertModuleSpecifier(node, false);
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
assertModuleSpecifier(node, node.exportClause?.kind === SyntaxKind.NamedExports);
|
||||
break;
|
||||
case SyntaxKind.ExportSpecifier: {
|
||||
const local = node.propertyName ?? node.name;
|
||||
if (local.kind === SyntaxKind.StringLiteral &&
|
||||
parent.kind === SyntaxKind.ExportDeclaration &&
|
||||
parent.moduleSpecifier?.kind !== SyntaxKind.StringLiteral) {
|
||||
throw (0, node_utils_1.createError)(local, 'A string literal cannot be used as a local exported binding without `from`.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.CallExpression:
|
||||
if (node.expression.kind === SyntaxKind.ImportKeyword &&
|
||||
node.arguments.length !== 1 &&
|
||||
node.arguments.length !== 2) {
|
||||
throw (0, node_utils_1.createError)(node.arguments.length > 1 ? node.arguments[2] : node, 'Dynamic import requires exactly one or two arguments.');
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
if (!node.name &&
|
||||
(!(0, node_utils_1.hasModifier)(ts.SyntaxKind.ExportKeyword, node) ||
|
||||
!(0, node_utils_1.hasModifier)(ts.SyntaxKind.DefaultKeyword, node))) {
|
||||
throw (0, node_utils_1.createError)(node, "A class declaration without the 'default' modifier must have a name.");
|
||||
}
|
||||
// intentional fallthrough
|
||||
case SyntaxKind.ClassExpression: {
|
||||
const heritageClauses = node.heritageClauses ?? [];
|
||||
let seenExtendsClause = false;
|
||||
let seenImplementsClause = false;
|
||||
for (const heritageClause of heritageClauses) {
|
||||
const { token, types } = heritageClause;
|
||||
if (types.length === 0) {
|
||||
throw (0, node_utils_1.createError)(heritageClause, `'${ts.tokenToString(token)}' list cannot be empty.`);
|
||||
}
|
||||
if (token === SyntaxKind.ExtendsKeyword) {
|
||||
if (seenExtendsClause) {
|
||||
throw (0, node_utils_1.createError)(heritageClause, "'extends' clause already seen.");
|
||||
}
|
||||
if (seenImplementsClause) {
|
||||
throw (0, node_utils_1.createError)(heritageClause, "'extends' clause must precede 'implements' clause.");
|
||||
}
|
||||
if (types.length > 1) {
|
||||
throw (0, node_utils_1.createError)(types[1], 'Classes can only extend a single class.');
|
||||
}
|
||||
seenExtendsClause = true;
|
||||
}
|
||||
else {
|
||||
// `implements`
|
||||
if (seenImplementsClause) {
|
||||
throw (0, node_utils_1.createError)(heritageClause, "'implements' clause already seen.");
|
||||
}
|
||||
for (const heritageType of heritageClause.types) {
|
||||
if (!(0, node_utils_1.isEntityNameExpression)(heritageType.expression) ||
|
||||
ts.isOptionalChain(heritageType.expression)) {
|
||||
throw (0, node_utils_1.createError)(heritageType, 'A class can only implement an identifier/qualified-name with optional type arguments.');
|
||||
}
|
||||
}
|
||||
seenImplementsClause = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.InterfaceDeclaration: {
|
||||
const interfaceHeritageClauses = node.heritageClauses ?? [];
|
||||
let seenExtendsClause = false;
|
||||
for (const heritageClause of interfaceHeritageClauses) {
|
||||
const { token, types } = heritageClause;
|
||||
if (token === SyntaxKind.ImplementsKeyword) {
|
||||
throw (0, node_utils_1.createError)(heritageClause, "Interface declaration cannot have 'implements' clause.");
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (token !== SyntaxKind.ExtendsKeyword) {
|
||||
throw (0, node_utils_1.createError)(heritageClause, 'Unexpected token.');
|
||||
}
|
||||
if (types.length === 0) {
|
||||
throw (0, node_utils_1.createError)(heritageClause, `'${ts.tokenToString(token)}' list cannot be empty.`);
|
||||
}
|
||||
if (seenExtendsClause) {
|
||||
throw (0, node_utils_1.createError)(heritageClause, "'extends' clause already seen.");
|
||||
}
|
||||
seenExtendsClause = true;
|
||||
for (const heritageType of heritageClause.types) {
|
||||
if (!(0, node_utils_1.isEntityNameExpression)(heritageType.expression) ||
|
||||
ts.isOptionalChain(heritageType.expression)) {
|
||||
throw (0, node_utils_1.createError)(heritageType, 'Interface declaration can only extend an identifier/qualified name with optional type arguments.');
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
if (node.parent.kind === SyntaxKind.InterfaceDeclaration ||
|
||||
node.parent.kind === SyntaxKind.TypeLiteral) {
|
||||
return;
|
||||
}
|
||||
// otherwise, it is a non-type accessor - intentional fallthrough
|
||||
case SyntaxKind.MethodDeclaration: {
|
||||
const isAbstract = (0, node_utils_1.hasModifier)(SyntaxKind.AbstractKeyword, node);
|
||||
if (isAbstract && node.body) {
|
||||
throw (0, node_utils_1.createError)(node.name, node.kind === SyntaxKind.GetAccessor ||
|
||||
node.kind === SyntaxKind.SetAccessor
|
||||
? 'An abstract accessor cannot have an implementation.'
|
||||
: `Method '${(0, node_utils_1.declarationNameToString)(node.name)}' cannot have an implementation because it is marked abstract.`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.MetaProperty: {
|
||||
const metaObject = (0, node_utils_1.getTextForTokenKind)(node.keywordToken);
|
||||
const metaPropertyName = node.name.text;
|
||||
if (metaObject === 'import') {
|
||||
if (metaPropertyName === 'defer' &&
|
||||
node.parent.kind !== SyntaxKind.CallExpression) {
|
||||
throw (0, node_utils_1.createError)(node, "'import.defer' is only valid when called. Use 'import.defer()' instead.");
|
||||
}
|
||||
if (metaPropertyName !== 'meta') {
|
||||
throw (0, node_utils_1.createError)(node, `'${metaPropertyName}' is not a valid meta-property for keyword 'import'.`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ObjectLiteralExpression: {
|
||||
if (!allowPattern) {
|
||||
for (const property of node.properties) {
|
||||
if ((property.kind === SyntaxKind.GetAccessor ||
|
||||
property.kind === SyntaxKind.SetAccessor ||
|
||||
property.kind === SyntaxKind.MethodDeclaration) &&
|
||||
!property.body) {
|
||||
throw (0, node_utils_1.createError)(property.end - 1, "'{' expected.", node.getSourceFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
if (node.isTypeOnly &&
|
||||
node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) {
|
||||
throw (0, node_utils_1.createError)(node, "An import alias cannot use 'import type'");
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ModuleDeclaration: {
|
||||
if (node.flags & ts.NodeFlags.GlobalAugmentation) {
|
||||
const { body } = node;
|
||||
if (body == null || body.kind === SyntaxKind.ModuleDeclaration) {
|
||||
throw (0, node_utils_1.createError)(node.body ?? node, 'Expected a valid module body');
|
||||
}
|
||||
const { name } = node;
|
||||
if (name.kind !== ts.SyntaxKind.Identifier) {
|
||||
throw (0, node_utils_1.createError)(name, 'global module augmentation must have an Identifier id');
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ts.isStringLiteral(node.name)) {
|
||||
return;
|
||||
}
|
||||
if (node.body == null) {
|
||||
throw (0, node_utils_1.createError)(node, 'Expected a module body');
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Fixme: confirm if it's possible
|
||||
if (node.name.kind !== ts.SyntaxKind.Identifier) {
|
||||
throw (0, node_utils_1.createError)(node.name, '`namespace`s must have an Identifier id');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement: {
|
||||
checkForStatementDeclaration(node);
|
||||
break;
|
||||
}
|
||||
// No default
|
||||
}
|
||||
}
|
||||
function checkForStatementDeclaration(node) {
|
||||
const { initializer, kind } = node;
|
||||
const loop = kind === SyntaxKind.ForInStatement ? 'for...in' : 'for...of';
|
||||
if (ts.isVariableDeclarationList(initializer)) {
|
||||
if (initializer.declarations.length !== 1) {
|
||||
throw (0, node_utils_1.createError)(initializer, `Only a single variable declaration is allowed in a '${loop}' statement.`);
|
||||
}
|
||||
const declaration = initializer.declarations[0];
|
||||
if (declaration.initializer) {
|
||||
throw (0, node_utils_1.createError)(declaration, `The variable declaration of a '${loop}' statement cannot have an initializer.`);
|
||||
}
|
||||
else if (declaration.type) {
|
||||
throw (0, node_utils_1.createError)(declaration, `The variable declaration of a '${loop}' statement cannot have a type annotation.`);
|
||||
}
|
||||
}
|
||||
else if (!(0, node_utils_1.isValidAssignmentTarget)(initializer) &&
|
||||
initializer.kind !== SyntaxKind.ObjectLiteralExpression &&
|
||||
initializer.kind !== SyntaxKind.ArrayLiteralExpression) {
|
||||
throw (0, node_utils_1.createError)(initializer, `The left-hand side of a '${loop}' statement must be a variable or a property access.`);
|
||||
}
|
||||
}
|
||||
function assertModuleSpecifier(node, allowNull) {
|
||||
if (!allowNull && node.moduleSpecifier == null) {
|
||||
throw (0, node_utils_1.createError)(node, 'Module specifier must be a string literal.');
|
||||
}
|
||||
if (node.moduleSpecifier &&
|
||||
node.moduleSpecifier.kind !== SyntaxKind.StringLiteral) {
|
||||
throw (0, node_utils_1.createError)(node.moduleSpecifier, 'Module specifier must be a string literal.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
// See https://github.com/nodejs/undici/issues/1740
|
||||
|
||||
export interface EventInit {
|
||||
bubbles?: boolean
|
||||
cancelable?: boolean
|
||||
composed?: boolean
|
||||
}
|
||||
|
||||
export interface EventListenerOptions {
|
||||
capture?: boolean
|
||||
}
|
||||
|
||||
export interface AddEventListenerOptions extends EventListenerOptions {
|
||||
once?: boolean
|
||||
passive?: boolean
|
||||
signal?: AbortSignal
|
||||
}
|
||||
|
||||
export type EventListenerOrEventListenerObject = EventListener | EventListenerObject
|
||||
|
||||
export interface EventListenerObject {
|
||||
handleEvent (object: Event): void
|
||||
}
|
||||
|
||||
export interface EventListener {
|
||||
(evt: Event): void
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
import type { Primitive } from "./helpers/typeAliases.js";
|
||||
import { util, type ZodParsedType } from "./helpers/util.js";
|
||||
import type { TypeOf, ZodType } from "./index.js";
|
||||
type allKeys<T> = T extends any ? keyof T : never;
|
||||
export type inferFlattenedErrors<T extends ZodType<any, any, any>, U = string> = typeToFlattenedError<TypeOf<T>, U>;
|
||||
export type typeToFlattenedError<T, U = string> = {
|
||||
formErrors: U[];
|
||||
fieldErrors: {
|
||||
[P in allKeys<T>]?: U[];
|
||||
};
|
||||
};
|
||||
export declare const ZodIssueCode: {
|
||||
custom: "custom";
|
||||
invalid_type: "invalid_type";
|
||||
too_big: "too_big";
|
||||
too_small: "too_small";
|
||||
not_multiple_of: "not_multiple_of";
|
||||
unrecognized_keys: "unrecognized_keys";
|
||||
invalid_union: "invalid_union";
|
||||
invalid_literal: "invalid_literal";
|
||||
invalid_union_discriminator: "invalid_union_discriminator";
|
||||
invalid_enum_value: "invalid_enum_value";
|
||||
invalid_arguments: "invalid_arguments";
|
||||
invalid_return_type: "invalid_return_type";
|
||||
invalid_date: "invalid_date";
|
||||
invalid_string: "invalid_string";
|
||||
invalid_intersection_types: "invalid_intersection_types";
|
||||
not_finite: "not_finite";
|
||||
};
|
||||
export type ZodIssueCode = keyof typeof ZodIssueCode;
|
||||
export type ZodIssueBase = {
|
||||
path: (string | number)[];
|
||||
message?: string | undefined;
|
||||
};
|
||||
export interface ZodInvalidTypeIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_type;
|
||||
expected: ZodParsedType;
|
||||
received: ZodParsedType;
|
||||
}
|
||||
export interface ZodInvalidLiteralIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_literal;
|
||||
expected: unknown;
|
||||
received: unknown;
|
||||
}
|
||||
export interface ZodUnrecognizedKeysIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.unrecognized_keys;
|
||||
keys: string[];
|
||||
}
|
||||
export interface ZodInvalidUnionIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_union;
|
||||
unionErrors: ZodError[];
|
||||
}
|
||||
export interface ZodInvalidUnionDiscriminatorIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_union_discriminator;
|
||||
options: Primitive[];
|
||||
}
|
||||
export interface ZodInvalidEnumValueIssue extends ZodIssueBase {
|
||||
received: string | number;
|
||||
code: typeof ZodIssueCode.invalid_enum_value;
|
||||
options: (string | number)[];
|
||||
}
|
||||
export interface ZodInvalidArgumentsIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_arguments;
|
||||
argumentsError: ZodError;
|
||||
}
|
||||
export interface ZodInvalidReturnTypeIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_return_type;
|
||||
returnTypeError: ZodError;
|
||||
}
|
||||
export interface ZodInvalidDateIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_date;
|
||||
}
|
||||
export type StringValidation = "email" | "url" | "emoji" | "uuid" | "nanoid" | "regex" | "cuid" | "cuid2" | "ulid" | "datetime" | "date" | "time" | "duration" | "ip" | "cidr" | "base64" | "jwt" | "base64url" | {
|
||||
includes: string;
|
||||
position?: number | undefined;
|
||||
} | {
|
||||
startsWith: string;
|
||||
} | {
|
||||
endsWith: string;
|
||||
};
|
||||
export interface ZodInvalidStringIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_string;
|
||||
validation: StringValidation;
|
||||
}
|
||||
export interface ZodTooSmallIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.too_small;
|
||||
minimum: number | bigint;
|
||||
inclusive: boolean;
|
||||
exact?: boolean;
|
||||
type: "array" | "string" | "number" | "set" | "date" | "bigint";
|
||||
}
|
||||
export interface ZodTooBigIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.too_big;
|
||||
maximum: number | bigint;
|
||||
inclusive: boolean;
|
||||
exact?: boolean;
|
||||
type: "array" | "string" | "number" | "set" | "date" | "bigint";
|
||||
}
|
||||
export interface ZodInvalidIntersectionTypesIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.invalid_intersection_types;
|
||||
}
|
||||
export interface ZodNotMultipleOfIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.not_multiple_of;
|
||||
multipleOf: number | bigint;
|
||||
}
|
||||
export interface ZodNotFiniteIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.not_finite;
|
||||
}
|
||||
export interface ZodCustomIssue extends ZodIssueBase {
|
||||
code: typeof ZodIssueCode.custom;
|
||||
params?: {
|
||||
[k: string]: any;
|
||||
};
|
||||
}
|
||||
export type DenormalizedError = {
|
||||
[k: string]: DenormalizedError | string[];
|
||||
};
|
||||
export type ZodIssueOptionalMessage = ZodInvalidTypeIssue | ZodInvalidLiteralIssue | ZodUnrecognizedKeysIssue | ZodInvalidUnionIssue | ZodInvalidUnionDiscriminatorIssue | ZodInvalidEnumValueIssue | ZodInvalidArgumentsIssue | ZodInvalidReturnTypeIssue | ZodInvalidDateIssue | ZodInvalidStringIssue | ZodTooSmallIssue | ZodTooBigIssue | ZodInvalidIntersectionTypesIssue | ZodNotMultipleOfIssue | ZodNotFiniteIssue | ZodCustomIssue;
|
||||
export type ZodIssue = ZodIssueOptionalMessage & {
|
||||
fatal?: boolean | undefined;
|
||||
message: string;
|
||||
};
|
||||
export declare const quotelessJson: (obj: any) => string;
|
||||
type recursiveZodFormattedError<T> = T extends [any, ...any[]] ? {
|
||||
[K in keyof T]?: ZodFormattedError<T[K]>;
|
||||
} : T extends any[] ? {
|
||||
[k: number]: ZodFormattedError<T[number]>;
|
||||
} : T extends object ? {
|
||||
[K in keyof T]?: ZodFormattedError<T[K]>;
|
||||
} : unknown;
|
||||
export type ZodFormattedError<T, U = string> = {
|
||||
_errors: U[];
|
||||
} & recursiveZodFormattedError<NonNullable<T>>;
|
||||
export type inferFormattedError<T extends ZodType<any, any, any>, U = string> = ZodFormattedError<TypeOf<T>, U>;
|
||||
export declare class ZodError<T = any> extends Error {
|
||||
issues: ZodIssue[];
|
||||
get errors(): ZodIssue[];
|
||||
constructor(issues: ZodIssue[]);
|
||||
format(): ZodFormattedError<T>;
|
||||
format<U>(mapper: (issue: ZodIssue) => U): ZodFormattedError<T, U>;
|
||||
static create: (issues: ZodIssue[]) => ZodError<any>;
|
||||
static assert(value: unknown): asserts value is ZodError;
|
||||
toString(): string;
|
||||
get message(): string;
|
||||
get isEmpty(): boolean;
|
||||
addIssue: (sub: ZodIssue) => void;
|
||||
addIssues: (subs?: ZodIssue[]) => void;
|
||||
flatten(): typeToFlattenedError<T>;
|
||||
flatten<U>(mapper?: (issue: ZodIssue) => U): typeToFlattenedError<T, U>;
|
||||
get formErrors(): typeToFlattenedError<T, string>;
|
||||
}
|
||||
type stripPath<T extends object> = T extends any ? util.OmitKeys<T, "path"> : never;
|
||||
export type IssueData = stripPath<ZodIssueOptionalMessage> & {
|
||||
path?: (string | number)[];
|
||||
fatal?: boolean | undefined;
|
||||
};
|
||||
export type ErrorMapCtx = {
|
||||
defaultError: string;
|
||||
data: any;
|
||||
};
|
||||
export type ZodErrorMap = (issue: ZodIssueOptionalMessage, _ctx: ErrorMapCtx) => {
|
||||
message: string;
|
||||
};
|
||||
export {};
|
||||
@@ -0,0 +1,7 @@
|
||||
Copyright 2023 Abdullah Atta
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,25 @@
|
||||
export {};
|
||||
|
||||
import { LockManager } from "worker_threads";
|
||||
|
||||
// lib.webworker has `WorkerNavigator` rather than `Navigator`, so conditionals use `onabort` instead of `onmessage`
|
||||
type _Navigator = typeof globalThis extends { onabort: any } ? {} : Navigator;
|
||||
interface Navigator {
|
||||
readonly hardwareConcurrency: number;
|
||||
readonly language: string;
|
||||
readonly languages: readonly string[];
|
||||
readonly locks: LockManager;
|
||||
readonly platform: string;
|
||||
readonly userAgent: string;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Navigator extends _Navigator {}
|
||||
var Navigator: typeof globalThis extends { onabort: any; Navigator: infer T } ? T : {
|
||||
prototype: Navigator;
|
||||
new(): Navigator;
|
||||
};
|
||||
|
||||
// Needs conditional inference for lib.dom and lib.webworker compatibility
|
||||
var navigator: typeof globalThis extends { onmessage: any; navigator: infer T } ? T : Navigator;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
export { default as ar } from "./ar.cjs";
|
||||
export { default as az } from "./az.cjs";
|
||||
export { default as be } from "./be.cjs";
|
||||
export { default as bg } from "./bg.cjs";
|
||||
export { default as ca } from "./ca.cjs";
|
||||
export { default as cs } from "./cs.cjs";
|
||||
export { default as da } from "./da.cjs";
|
||||
export { default as de } from "./de.cjs";
|
||||
export { default as el } from "./el.cjs";
|
||||
export { default as en } from "./en.cjs";
|
||||
export { default as eo } from "./eo.cjs";
|
||||
export { default as es } from "./es.cjs";
|
||||
export { default as fa } from "./fa.cjs";
|
||||
export { default as fi } from "./fi.cjs";
|
||||
export { default as fr } from "./fr.cjs";
|
||||
export { default as frCA } from "./fr-CA.cjs";
|
||||
export { default as he } from "./he.cjs";
|
||||
export { default as hr } from "./hr.cjs";
|
||||
export { default as hu } from "./hu.cjs";
|
||||
export { default as hy } from "./hy.cjs";
|
||||
export { default as id } from "./id.cjs";
|
||||
export { default as is } from "./is.cjs";
|
||||
export { default as it } from "./it.cjs";
|
||||
export { default as ja } from "./ja.cjs";
|
||||
export { default as ka } from "./ka.cjs";
|
||||
export { default as kh } from "./kh.cjs";
|
||||
export { default as km } from "./km.cjs";
|
||||
export { default as ko } from "./ko.cjs";
|
||||
export { default as lt } from "./lt.cjs";
|
||||
export { default as mk } from "./mk.cjs";
|
||||
export { default as ms } from "./ms.cjs";
|
||||
export { default as nl } from "./nl.cjs";
|
||||
export { default as no } from "./no.cjs";
|
||||
export { default as ota } from "./ota.cjs";
|
||||
export { default as ps } from "./ps.cjs";
|
||||
export { default as pl } from "./pl.cjs";
|
||||
export { default as pt } from "./pt.cjs";
|
||||
export { default as ro } from "./ro.cjs";
|
||||
export { default as ru } from "./ru.cjs";
|
||||
export { default as sl } from "./sl.cjs";
|
||||
export { default as sv } from "./sv.cjs";
|
||||
export { default as ta } from "./ta.cjs";
|
||||
export { default as th } from "./th.cjs";
|
||||
export { default as tr } from "./tr.cjs";
|
||||
export { default as ua } from "./ua.cjs";
|
||||
export { default as uk } from "./uk.cjs";
|
||||
export { default as ur } from "./ur.cjs";
|
||||
export { default as uz } from "./uz.cjs";
|
||||
export { default as vi } from "./vi.cjs";
|
||||
export { default as zhCN } from "./zh-CN.cjs";
|
||||
export { default as zhTW } from "./zh-TW.cjs";
|
||||
export { default as yo } from "./yo.cjs";
|
||||
@@ -0,0 +1,3 @@
|
||||
export { A as AfterAllListener, i as AfterEachListener, j as AroundAllListener, k as AroundEachListener, B as BeforeAllListener, l as BeforeEachListener, C as CancelReason, m as FailureScreenshotArtifact, c as File, F as FileSpecification, n as Fixture, o as FixtureFn, p as FixtureOptions, q as Fixtures, I as ImportDuration, r as InferFixturesTypes, O as OnTestFailedHandler, s as OnTestFinishedHandler, R as Retry, t as RunMode, u as RuntimeContext, v as SequenceHooks, w as SequenceSetupFiles, x as SerializableRetry, S as Suite, g as SuiteAPI, h as SuiteCollector, y as SuiteFactory, b as SuiteHooks, z as SuiteOptions, e as Task, D as TaskBase, E as TaskCustomOptions, G as TaskEventPack, H as TaskHook, J as TaskMeta, K as TaskPopulated, L as TaskResult, M as TaskResultPack, N as TaskState, d as TaskUpdateEvent, a as Test, f as TestAPI, P as TestAnnotation, Q as TestAnnotationArtifact, U as TestAnnotationLocation, T as TestArtifact, W as TestArtifactBase, X as TestArtifactLocation, Y as TestArtifactRegistry, Z as TestAttachment, _ as TestContext, $ as TestFunction, a0 as TestOptions, a1 as TestTagDefinition, a2 as TestTags, a3 as Use, a4 as VisualRegressionArtifact, V as VitestRunner, a5 as VitestRunnerConfig, a6 as VitestRunnerConstructor, a7 as VitestRunnerImportSource } from './tasks.d-DEYaIMIu.js';
|
||||
import '@vitest/utils';
|
||||
import '@vitest/utils/diff';
|
||||
@@ -0,0 +1,132 @@
|
||||
# json-stable-stringify
|
||||
|
||||
This is the same as https://github.com/substack/json-stable-stringify but it doesn't depend on libraries without licenses (jsonify).
|
||||
|
||||
deterministic version of `JSON.stringify()` so you can get a consistent hash
|
||||
from stringified results
|
||||
|
||||
You can also pass in a custom comparison function.
|
||||
|
||||
[](https://ci.testling.com/substack/json-stable-stringify)
|
||||
|
||||
[](http://travis-ci.org/substack/json-stable-stringify)
|
||||
|
||||
# example
|
||||
|
||||
``` js
|
||||
var stringify = require('json-stable-stringify');
|
||||
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
|
||||
console.log(stringify(obj));
|
||||
```
|
||||
|
||||
output:
|
||||
|
||||
```
|
||||
{"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8}
|
||||
```
|
||||
|
||||
# methods
|
||||
|
||||
``` js
|
||||
var stringify = require('json-stable-stringify')
|
||||
```
|
||||
|
||||
## var str = stringify(obj, opts)
|
||||
|
||||
Return a deterministic stringified string `str` from the object `obj`.
|
||||
|
||||
## options
|
||||
|
||||
### cmp
|
||||
|
||||
If `opts` is given, you can supply an `opts.cmp` to have a custom comparison
|
||||
function for object keys. Your function `opts.cmp` is called with these
|
||||
parameters:
|
||||
|
||||
``` js
|
||||
opts.cmp({ key: akey, value: avalue }, { key: bkey, value: bvalue })
|
||||
```
|
||||
|
||||
For example, to sort on the object key names in reverse order you could write:
|
||||
|
||||
``` js
|
||||
var stringify = require('json-stable-stringify');
|
||||
|
||||
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
|
||||
var s = stringify(obj, function (a, b) {
|
||||
return a.key < b.key ? 1 : -1;
|
||||
});
|
||||
console.log(s);
|
||||
```
|
||||
|
||||
which results in the output string:
|
||||
|
||||
```
|
||||
{"c":8,"b":[{"z":6,"y":5,"x":4},7],"a":3}
|
||||
```
|
||||
|
||||
Or if you wanted to sort on the object values in reverse order, you could write:
|
||||
|
||||
```
|
||||
var stringify = require('json-stable-stringify');
|
||||
|
||||
var obj = { d: 6, c: 5, b: [{z:3,y:2,x:1},9], a: 10 };
|
||||
var s = stringify(obj, function (a, b) {
|
||||
return a.value < b.value ? 1 : -1;
|
||||
});
|
||||
console.log(s);
|
||||
```
|
||||
|
||||
which outputs:
|
||||
|
||||
```
|
||||
{"d":6,"c":5,"b":[{"z":3,"y":2,"x":1},9],"a":10}
|
||||
```
|
||||
|
||||
### space
|
||||
|
||||
If you specify `opts.space`, it will indent the output for pretty-printing.
|
||||
Valid values are strings (e.g. `{space: \t}`) or a number of spaces
|
||||
(`{space: 3}`).
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
var obj = { b: 1, a: { foo: 'bar', and: [1, 2, 3] } };
|
||||
var s = stringify(obj, { space: ' ' });
|
||||
console.log(s);
|
||||
```
|
||||
|
||||
which outputs:
|
||||
|
||||
```
|
||||
{
|
||||
"a": {
|
||||
"and": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"foo": "bar"
|
||||
},
|
||||
"b": 1
|
||||
}
|
||||
```
|
||||
|
||||
### replacer
|
||||
|
||||
The replacer parameter is a function `opts.replacer(key, value)` that behaves
|
||||
the same as the replacer
|
||||
[from the core JSON object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_native_JSON#The_replacer_parameter).
|
||||
|
||||
# install
|
||||
|
||||
With [npm](https://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm install json-stable-stringify
|
||||
```
|
||||
|
||||
# license
|
||||
|
||||
MIT
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
||||
import type { MessageIds, Options } from '../naming-convention';
|
||||
import type { IndividualAndMetaSelectorsString, MetaSelectors, Modifiers, ModifiersString, PredefinedFormats, PredefinedFormatsString, Selectors, SelectorsString, TypeModifiers, TypeModifiersString, UnderscoreOptions, UnderscoreOptionsString } from './enums';
|
||||
export interface MatchRegex {
|
||||
match: boolean;
|
||||
regex: string;
|
||||
}
|
||||
export interface Selector {
|
||||
custom?: MatchRegex;
|
||||
filter?: string | MatchRegex;
|
||||
format: PredefinedFormatsString[] | null;
|
||||
leadingUnderscore?: UnderscoreOptionsString;
|
||||
modifiers?: ModifiersString[];
|
||||
prefix?: string[];
|
||||
selector: IndividualAndMetaSelectorsString | IndividualAndMetaSelectorsString[];
|
||||
suffix?: string[];
|
||||
trailingUnderscore?: UnderscoreOptionsString;
|
||||
types?: TypeModifiersString[];
|
||||
}
|
||||
export interface NormalizedMatchRegex {
|
||||
match: boolean;
|
||||
regex: RegExp;
|
||||
}
|
||||
export interface NormalizedSelector {
|
||||
custom: NormalizedMatchRegex | null;
|
||||
filter: NormalizedMatchRegex | null;
|
||||
format: PredefinedFormats[] | null;
|
||||
leadingUnderscore: UnderscoreOptions | null;
|
||||
modifiers: Modifiers[] | null;
|
||||
modifierWeight: number;
|
||||
prefix: string[] | null;
|
||||
selector: MetaSelectors | Selectors;
|
||||
suffix: string[] | null;
|
||||
trailingUnderscore: UnderscoreOptions | null;
|
||||
types: TypeModifiers[] | null;
|
||||
}
|
||||
export type ValidatorFunction = (node: TSESTree.Identifier | TSESTree.Literal | TSESTree.PrivateIdentifier, modifiers?: Set<Modifiers>) => void;
|
||||
export type ParsedOptions = Record<SelectorsString, ValidatorFunction>;
|
||||
export type Context = Readonly<TSESLint.RuleContext<MessageIds, Options>>;
|
||||
@@ -0,0 +1,114 @@
|
||||
'use strict'
|
||||
|
||||
const { describe, test } = require('node:test')
|
||||
const tspl = require('@matteo.collina/tspl')
|
||||
|
||||
const { sink, match, once } = require('./helper')
|
||||
const pino = require('../')
|
||||
|
||||
describe('log method hook', () => {
|
||||
test('gets invoked', async t => {
|
||||
const plan = tspl(t, { plan: 7 })
|
||||
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
hooks: {
|
||||
logMethod (args, method, level) {
|
||||
plan.equal(Array.isArray(args), true)
|
||||
plan.equal(typeof level, 'number')
|
||||
plan.equal(args.length, 3)
|
||||
plan.equal(level, this.levels.values.info)
|
||||
plan.deepEqual(args, ['a', 'b', 'c'])
|
||||
|
||||
plan.equal(typeof method, 'function')
|
||||
plan.equal(method.name, 'LOG')
|
||||
|
||||
method.apply(this, [args.join('-')])
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.info('a', 'b', 'c')
|
||||
match(await o, { msg: 'a-b-c' })
|
||||
})
|
||||
|
||||
test('fatal method invokes hook', async t => {
|
||||
const plan = tspl(t, { plan: 1 })
|
||||
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
hooks: {
|
||||
logMethod (args, method) {
|
||||
plan.ok(true)
|
||||
method.apply(this, [args.join('-')])
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.fatal('a')
|
||||
match(await o, { msg: 'a' })
|
||||
})
|
||||
|
||||
test('children get the hook', async t => {
|
||||
const plan = tspl(t, { plan: 2 })
|
||||
|
||||
const stream = sink()
|
||||
const root = pino({
|
||||
hooks: {
|
||||
logMethod (args, method) {
|
||||
plan.ok(true)
|
||||
method.apply(this, [args.join('-')])
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
const child = root.child({ child: 'one' })
|
||||
const grandchild = child.child({ child: 'two' })
|
||||
|
||||
let o = once(stream, 'data')
|
||||
child.info('a', 'b')
|
||||
match(await o, { msg: 'a-b' })
|
||||
|
||||
o = once(stream, 'data')
|
||||
grandchild.info('c', 'd')
|
||||
match(await o, { msg: 'c-d' })
|
||||
})
|
||||
|
||||
test('get log level', async t => {
|
||||
const plan = tspl(t, { plan: 2 })
|
||||
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
hooks: {
|
||||
logMethod (args, method, level) {
|
||||
plan.equal(typeof level, 'number')
|
||||
plan.equal(level, this.levels.values.error)
|
||||
|
||||
method.apply(this, [args.join('-')])
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.error('a')
|
||||
match(await o, { msg: 'a' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('streamWrite hook', () => {
|
||||
test('gets invoked', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
hooks: {
|
||||
streamWrite (s) {
|
||||
return s.replaceAll('redact-me', 'XXX')
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.info('hide redact-me in this string')
|
||||
match(await o, { msg: 'hide XXX in this string' })
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,622 @@
|
||||
import type * as core from "../core/index.js";
|
||||
import type * as JSONSchema from "./json-schema.js";
|
||||
import { type $ZodRegistry, globalRegistry } from "./registries.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import type { StandardJSONSchemaV1, StandardSchemaWithJSONProps } from "./standard-schema.js";
|
||||
|
||||
export type Processor<T extends schemas.$ZodType = schemas.$ZodType> = (
|
||||
schema: T,
|
||||
ctx: ToJSONSchemaContext,
|
||||
json: JSONSchema.BaseSchema,
|
||||
params: ProcessParams
|
||||
) => void;
|
||||
|
||||
export interface JSONSchemaGeneratorParams {
|
||||
processors: Record<string, Processor>;
|
||||
/** A registry used to look up metadata for each schema. Any schema with an `id` property will be extracted as a $def.
|
||||
* @default globalRegistry */
|
||||
metadata?: $ZodRegistry<Record<string, any>>;
|
||||
/** The JSON Schema version to target.
|
||||
* - `"draft-2020-12"` — Default. JSON Schema Draft 2020-12
|
||||
* - `"draft-07"` — JSON Schema Draft 7
|
||||
* - `"draft-04"` — JSON Schema Draft 4
|
||||
* - `"openapi-3.0"` — OpenAPI 3.0 Schema Object */
|
||||
target?: "draft-04" | "draft-07" | "draft-2020-12" | "openapi-3.0" | ({} & string) | undefined;
|
||||
/** How to handle unrepresentable types.
|
||||
* - `"throw"` — Default. Unrepresentable types throw an error
|
||||
* - `"any"` — Unrepresentable types become `{}` */
|
||||
unrepresentable?: "throw" | "any";
|
||||
/** Arbitrary custom logic that can be used to modify the generated JSON Schema. */
|
||||
override?: (ctx: {
|
||||
zodSchema: schemas.$ZodTypes;
|
||||
jsonSchema: JSONSchema.BaseSchema;
|
||||
path: (string | number)[];
|
||||
}) => void;
|
||||
/** Whether to extract the `"input"` or `"output"` type. Relevant to transforms, defaults, coerced primitives, etc.
|
||||
* - `"output"` — Default. Convert the output schema.
|
||||
* - `"input"` — Convert the input schema. */
|
||||
io?: "input" | "output";
|
||||
cycles?: "ref" | "throw";
|
||||
reused?: "ref" | "inline";
|
||||
external?:
|
||||
| {
|
||||
registry: $ZodRegistry<{ id?: string | undefined }>;
|
||||
uri?: ((id: string) => string) | undefined;
|
||||
defs: Record<string, JSONSchema.BaseSchema>;
|
||||
}
|
||||
| undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for the toJSONSchema function.
|
||||
*/
|
||||
export type ToJSONSchemaParams = Omit<JSONSchemaGeneratorParams, "processors" | "external">;
|
||||
|
||||
/**
|
||||
* Parameters for the toJSONSchema function when passing a registry.
|
||||
*/
|
||||
export interface RegistryToJSONSchemaParams extends ToJSONSchemaParams {
|
||||
uri?: (id: string) => string;
|
||||
}
|
||||
|
||||
export interface ProcessParams {
|
||||
schemaPath: schemas.$ZodType[];
|
||||
path: (string | number)[];
|
||||
}
|
||||
|
||||
export interface Seen {
|
||||
/** JSON Schema result for this Zod schema */
|
||||
schema: JSONSchema.BaseSchema;
|
||||
/** A cached version of the schema that doesn't get overwritten during ref resolution */
|
||||
def?: JSONSchema.BaseSchema;
|
||||
defId?: string | undefined;
|
||||
/** Number of times this schema was encountered during traversal */
|
||||
count: number;
|
||||
/** Cycle path */
|
||||
cycle?: (string | number)[] | undefined;
|
||||
isParent?: boolean | undefined;
|
||||
/** Schema to inherit JSON Schema properties from (set by processor for wrappers) */
|
||||
ref?: schemas.$ZodType | null;
|
||||
/** JSON Schema property path for this schema */
|
||||
path?: (string | number)[] | undefined;
|
||||
}
|
||||
|
||||
export interface ToJSONSchemaContext {
|
||||
processors: Record<string, Processor>;
|
||||
metadataRegistry: $ZodRegistry<Record<string, any>>;
|
||||
target: "draft-04" | "draft-07" | "draft-2020-12" | "openapi-3.0" | ({} & string);
|
||||
unrepresentable: "throw" | "any";
|
||||
override: (ctx: {
|
||||
// must be schemas.$ZodType to prevent recursive type resolution error
|
||||
zodSchema: schemas.$ZodType;
|
||||
jsonSchema: JSONSchema.BaseSchema;
|
||||
path: (string | number)[];
|
||||
}) => void;
|
||||
io: "input" | "output";
|
||||
counter: number;
|
||||
seen: Map<schemas.$ZodType, Seen>;
|
||||
cycles: "ref" | "throw";
|
||||
reused: "ref" | "inline";
|
||||
external?:
|
||||
| {
|
||||
registry: $ZodRegistry<{ id?: string | undefined }>;
|
||||
uri?: ((id: string) => string) | undefined;
|
||||
defs: Record<string, JSONSchema.BaseSchema>;
|
||||
}
|
||||
| undefined;
|
||||
}
|
||||
|
||||
// function initializeContext<T extends schemas.$ZodType>(inputs: JSONSchemaGeneratorParams<T>): ToJSONSchemaContext<T> {
|
||||
// return {
|
||||
// processor: inputs.processor,
|
||||
// metadataRegistry: inputs.metadata ?? globalRegistry,
|
||||
// target: inputs.target ?? "draft-2020-12",
|
||||
// unrepresentable: inputs.unrepresentable ?? "throw",
|
||||
// };
|
||||
// }
|
||||
|
||||
export function initializeContext(params: JSONSchemaGeneratorParams): ToJSONSchemaContext {
|
||||
// Normalize target: convert old non-hyphenated versions to hyphenated versions
|
||||
let target: ToJSONSchemaContext["target"] = params?.target ?? "draft-2020-12";
|
||||
if (target === "draft-4") target = "draft-04";
|
||||
if (target === "draft-7") target = "draft-07";
|
||||
|
||||
return {
|
||||
processors: params.processors ?? {},
|
||||
metadataRegistry: params?.metadata ?? globalRegistry,
|
||||
target,
|
||||
unrepresentable: params?.unrepresentable ?? "throw",
|
||||
override: (params?.override as any) ?? (() => {}),
|
||||
io: params?.io ?? "output",
|
||||
counter: 0,
|
||||
seen: new Map(),
|
||||
cycles: params?.cycles ?? "ref",
|
||||
reused: params?.reused ?? "inline",
|
||||
external: params?.external ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function process<T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
ctx: ToJSONSchemaContext,
|
||||
_params: ProcessParams = { path: [], schemaPath: [] }
|
||||
): JSONSchema.BaseSchema {
|
||||
const def = schema._zod.def as schemas.$ZodTypes["_zod"]["def"];
|
||||
|
||||
// check for schema in seens
|
||||
const seen = ctx.seen.get(schema);
|
||||
|
||||
if (seen) {
|
||||
seen.count++;
|
||||
|
||||
// check if cycle
|
||||
const isCycle = _params.schemaPath.includes(schema);
|
||||
if (isCycle) {
|
||||
seen.cycle = _params.path;
|
||||
}
|
||||
|
||||
return seen.schema;
|
||||
}
|
||||
|
||||
// initialize
|
||||
const result: Seen = { schema: {}, count: 1, cycle: undefined, path: _params.path };
|
||||
ctx.seen.set(schema, result);
|
||||
|
||||
// custom method overrides default behavior
|
||||
const overrideSchema = schema._zod.toJSONSchema?.();
|
||||
if (overrideSchema) {
|
||||
result.schema = overrideSchema as any;
|
||||
} else {
|
||||
const params = {
|
||||
..._params,
|
||||
schemaPath: [..._params.schemaPath, schema],
|
||||
path: _params.path,
|
||||
};
|
||||
|
||||
if (schema._zod.processJSONSchema) {
|
||||
schema._zod.processJSONSchema(ctx, result.schema, params);
|
||||
} else {
|
||||
const _json = result.schema;
|
||||
const processor = ctx.processors[def.type];
|
||||
if (!processor) {
|
||||
throw new Error(`[toJSONSchema]: Non-representable type encountered: ${def.type}`);
|
||||
}
|
||||
processor(schema, ctx, _json, params);
|
||||
}
|
||||
|
||||
const parent = schema._zod.parent as T;
|
||||
|
||||
if (parent) {
|
||||
// Also set ref if processor didn't (for inheritance)
|
||||
if (!result.ref) result.ref = parent;
|
||||
process(parent, ctx, params);
|
||||
ctx.seen.get(parent)!.isParent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// metadata
|
||||
const meta = ctx.metadataRegistry.get(schema);
|
||||
if (meta) Object.assign(result.schema, meta);
|
||||
|
||||
if (ctx.io === "input" && isTransforming(schema)) {
|
||||
// examples/defaults only apply to output type of pipe
|
||||
delete result.schema.examples;
|
||||
delete result.schema.default;
|
||||
}
|
||||
|
||||
// set prefault as default
|
||||
if (ctx.io === "input" && "_prefault" in result.schema) result.schema.default ??= result.schema._prefault;
|
||||
delete result.schema._prefault;
|
||||
|
||||
// pulling fresh from ctx.seen in case it was overwritten
|
||||
const _result = ctx.seen.get(schema)!;
|
||||
|
||||
return _result.schema;
|
||||
}
|
||||
|
||||
export function extractDefs<T extends schemas.$ZodType>(
|
||||
ctx: ToJSONSchemaContext,
|
||||
schema: T
|
||||
// params: EmitParams
|
||||
): void {
|
||||
// iterate over seen map;
|
||||
const root = ctx.seen.get(schema);
|
||||
|
||||
if (!root) throw new Error("Unprocessed schema. This is a bug in Zod.");
|
||||
|
||||
// Track ids to detect duplicates across different schemas
|
||||
const idToSchema = new Map<string, schemas.$ZodType>();
|
||||
for (const entry of ctx.seen.entries()) {
|
||||
const id = ctx.metadataRegistry.get(entry[0])?.id;
|
||||
if (id) {
|
||||
const existing = idToSchema.get(id);
|
||||
if (existing && existing !== entry[0]) {
|
||||
throw new Error(
|
||||
`Duplicate schema id "${id}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`
|
||||
);
|
||||
}
|
||||
idToSchema.set(id, entry[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// returns a ref to the schema
|
||||
// defId will be empty if the ref points to an external schema (or #)
|
||||
const makeURI = (entry: [schemas.$ZodType<unknown, unknown>, Seen]): { ref: string; defId?: string } => {
|
||||
// comparing the seen objects because sometimes
|
||||
// multiple schemas map to the same seen object.
|
||||
// e.g. lazy
|
||||
|
||||
// external is configured
|
||||
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
||||
if (ctx.external) {
|
||||
const externalId = ctx.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${ctx.counter++}`;
|
||||
|
||||
// check if schema is in the external registry
|
||||
const uriGenerator = ctx.external.uri ?? ((id: string) => id);
|
||||
if (externalId) {
|
||||
return { ref: uriGenerator(externalId) };
|
||||
}
|
||||
|
||||
// otherwise, add to __shared
|
||||
const id: string = entry[1].defId ?? (entry[1].schema.id as string) ?? `schema${ctx.counter++}`;
|
||||
entry[1].defId = id; // set defId so it will be reused if needed
|
||||
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
|
||||
}
|
||||
|
||||
if (entry[1] === root) {
|
||||
return { ref: "#" };
|
||||
}
|
||||
|
||||
// self-contained schema
|
||||
const uriPrefix = `#`;
|
||||
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
||||
const defId = entry[1].schema.id ?? `__schema${ctx.counter++}`;
|
||||
return { defId, ref: defUriPrefix + defId };
|
||||
};
|
||||
|
||||
// stored cached version in `def` property
|
||||
// remove all properties, set $ref
|
||||
const extractToDef = (entry: [schemas.$ZodType<unknown, unknown>, Seen]): void => {
|
||||
// if the schema is already a reference, do not extract it
|
||||
if (entry[1].schema.$ref) {
|
||||
return;
|
||||
}
|
||||
const seen = entry[1];
|
||||
const { ref, defId } = makeURI(entry);
|
||||
|
||||
seen.def = { ...seen.schema };
|
||||
// defId won't be set if the schema is a reference to an external schema
|
||||
// or if the schema is the root schema
|
||||
if (defId) seen.defId = defId;
|
||||
// wipe away all properties except $ref
|
||||
const schema = seen.schema;
|
||||
for (const key in schema) {
|
||||
delete schema[key];
|
||||
}
|
||||
schema.$ref = ref;
|
||||
};
|
||||
|
||||
// throw on cycles
|
||||
|
||||
// break cycles
|
||||
if (ctx.cycles === "throw") {
|
||||
for (const entry of ctx.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
if (seen.cycle) {
|
||||
throw new Error(
|
||||
"Cycle detected: " +
|
||||
`#/${seen.cycle?.join("/")}/<root>` +
|
||||
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extract schemas into $defs
|
||||
for (const entry of ctx.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
|
||||
// convert root schema to # $ref
|
||||
if (schema === entry[0]) {
|
||||
extractToDef(entry); // this has special handling for the root schema
|
||||
continue;
|
||||
}
|
||||
|
||||
// extract schemas that are in the external registry
|
||||
if (ctx.external) {
|
||||
const ext = ctx.external.registry.get(entry[0])?.id;
|
||||
if (schema !== entry[0] && ext) {
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// extract schemas with `id` meta
|
||||
const id = ctx.metadataRegistry.get(entry[0])?.id;
|
||||
if (id) {
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
// break cycles
|
||||
if (seen.cycle) {
|
||||
// any
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
// extract reused schemas
|
||||
if (seen.count > 1) {
|
||||
if (ctx.reused === "ref") {
|
||||
extractToDef(entry);
|
||||
// biome-ignore lint:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function finalize<T extends schemas.$ZodType>(
|
||||
ctx: ToJSONSchemaContext,
|
||||
schema: T
|
||||
): ZodStandardJSONSchemaPayload<T> {
|
||||
const root = ctx.seen.get(schema);
|
||||
if (!root) throw new Error("Unprocessed schema. This is a bug in Zod.");
|
||||
|
||||
// flatten refs - inherit properties from parent schemas
|
||||
const flattenRef = (zodSchema: schemas.$ZodType) => {
|
||||
const seen = ctx.seen.get(zodSchema)!;
|
||||
|
||||
// already processed
|
||||
if (seen.ref === null) return;
|
||||
|
||||
const schema = seen.def ?? seen.schema;
|
||||
const _cached = { ...schema };
|
||||
|
||||
const ref = seen.ref;
|
||||
seen.ref = null; // prevent infinite recursion
|
||||
|
||||
if (ref) {
|
||||
flattenRef(ref);
|
||||
|
||||
const refSeen = ctx.seen.get(ref)!;
|
||||
const refSchema = refSeen.schema;
|
||||
|
||||
// merge referenced schema into current
|
||||
if (refSchema.$ref && (ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0")) {
|
||||
// older drafts can't combine $ref with other properties
|
||||
schema.allOf = schema.allOf ?? [];
|
||||
schema.allOf.push(refSchema);
|
||||
} else {
|
||||
Object.assign(schema, refSchema);
|
||||
}
|
||||
// restore child's own properties (child wins)
|
||||
Object.assign(schema, _cached);
|
||||
|
||||
const isParentRef = zodSchema._zod.parent === ref;
|
||||
|
||||
// For parent chain, child is a refinement - remove parent-only properties
|
||||
if (isParentRef) {
|
||||
for (const key in schema) {
|
||||
if (key === "$ref" || key === "allOf") continue;
|
||||
if (!(key in _cached)) {
|
||||
delete schema[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When ref was extracted to $defs, remove properties that match the definition
|
||||
if (refSchema.$ref && refSeen.def) {
|
||||
for (const key in schema) {
|
||||
if (key === "$ref" || key === "allOf") continue;
|
||||
if (key in refSeen.def && JSON.stringify(schema[key]) === JSON.stringify(refSeen.def[key])) {
|
||||
delete schema[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If parent was extracted (has $ref), propagate $ref to this schema
|
||||
// This handles cases like: readonly().meta({id}).describe()
|
||||
// where processor sets ref to innerType but parent should be referenced
|
||||
const parent = zodSchema._zod.parent;
|
||||
if (parent && parent !== ref) {
|
||||
// Ensure parent is processed first so its def has inherited properties
|
||||
flattenRef(parent);
|
||||
const parentSeen = ctx.seen.get(parent);
|
||||
if (parentSeen?.schema.$ref) {
|
||||
schema.$ref = parentSeen.schema.$ref;
|
||||
// De-duplicate with parent's definition
|
||||
if (parentSeen.def) {
|
||||
for (const key in schema) {
|
||||
if (key === "$ref" || key === "allOf") continue;
|
||||
if (key in parentSeen.def && JSON.stringify(schema[key]) === JSON.stringify(parentSeen.def[key])) {
|
||||
delete schema[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// execute overrides
|
||||
ctx.override({
|
||||
zodSchema: zodSchema as schemas.$ZodTypes,
|
||||
jsonSchema: schema,
|
||||
path: seen.path ?? [],
|
||||
});
|
||||
};
|
||||
|
||||
for (const entry of [...ctx.seen.entries()].reverse()) {
|
||||
flattenRef(entry[0]);
|
||||
}
|
||||
|
||||
const result: JSONSchema.BaseSchema = {};
|
||||
if (ctx.target === "draft-2020-12") {
|
||||
result.$schema = "https://json-schema.org/draft/2020-12/schema";
|
||||
} else if (ctx.target === "draft-07") {
|
||||
result.$schema = "http://json-schema.org/draft-07/schema#";
|
||||
} else if (ctx.target === "draft-04") {
|
||||
result.$schema = "http://json-schema.org/draft-04/schema#";
|
||||
} else if (ctx.target === "openapi-3.0") {
|
||||
// OpenAPI 3.0 schema objects should not include a $schema property
|
||||
} else {
|
||||
// Arbitrary string values are allowed but won't have a $schema property set
|
||||
}
|
||||
|
||||
if (ctx.external?.uri) {
|
||||
const id = ctx.external.registry.get(schema)?.id;
|
||||
if (!id) throw new Error("Schema is missing an `id` property");
|
||||
result.$id = ctx.external.uri(id);
|
||||
}
|
||||
|
||||
Object.assign(result, root.def ?? root.schema);
|
||||
|
||||
// The `id` in `.meta()` is a Zod-specific registration tag used to extract
|
||||
// schemas into $defs — it is not user-facing JSON Schema metadata. Strip it
|
||||
// from the output body where it would otherwise leak. The id is preserved
|
||||
// implicitly via the $defs key (and via $ref paths).
|
||||
const rootMetaId = ctx.metadataRegistry.get(schema)?.id;
|
||||
if (rootMetaId !== undefined && result.id === rootMetaId) delete result.id;
|
||||
|
||||
// build defs object
|
||||
const defs: JSONSchema.BaseSchema["$defs"] = ctx.external?.defs ?? {};
|
||||
for (const entry of ctx.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
if (seen.def && seen.defId) {
|
||||
if (seen.def.id === seen.defId) delete seen.def.id;
|
||||
defs[seen.defId] = seen.def;
|
||||
}
|
||||
}
|
||||
|
||||
// set definitions in result
|
||||
if (ctx.external) {
|
||||
} else {
|
||||
if (Object.keys(defs).length > 0) {
|
||||
if (ctx.target === "draft-2020-12") {
|
||||
result.$defs = defs;
|
||||
} else {
|
||||
result.definitions = defs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// this "finalizes" this schema and ensures all cycles are removed
|
||||
// each call to finalize() is functionally independent
|
||||
// though the seen map is shared
|
||||
const finalized = JSON.parse(JSON.stringify(result));
|
||||
Object.defineProperty(finalized, "~standard", {
|
||||
value: {
|
||||
...schema["~standard"],
|
||||
jsonSchema: {
|
||||
input: createStandardJSONSchemaMethod(schema, "input", ctx.processors),
|
||||
output: createStandardJSONSchemaMethod(schema, "output", ctx.processors),
|
||||
},
|
||||
},
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
});
|
||||
|
||||
return finalized;
|
||||
} catch (_err) {
|
||||
throw new Error("Error converting schema to JSON.");
|
||||
}
|
||||
}
|
||||
|
||||
function isTransforming(
|
||||
_schema: schemas.$ZodType,
|
||||
_ctx?: {
|
||||
seen: Set<schemas.$ZodType>;
|
||||
}
|
||||
): boolean {
|
||||
const ctx = _ctx ?? { seen: new Set() };
|
||||
|
||||
if (ctx.seen.has(_schema)) return false;
|
||||
ctx.seen.add(_schema);
|
||||
|
||||
const def = (_schema as schemas.$ZodTypes)._zod.def;
|
||||
|
||||
if (def.type === "transform") return true;
|
||||
|
||||
if (def.type === "array") return isTransforming(def.element, ctx);
|
||||
if (def.type === "set") return isTransforming(def.valueType, ctx);
|
||||
if (def.type === "lazy") return isTransforming(def.getter(), ctx);
|
||||
|
||||
if (
|
||||
def.type === "promise" ||
|
||||
def.type === "optional" ||
|
||||
def.type === "nonoptional" ||
|
||||
def.type === "nullable" ||
|
||||
def.type === "readonly" ||
|
||||
def.type === "default" ||
|
||||
def.type === "prefault"
|
||||
) {
|
||||
return isTransforming(def.innerType, ctx);
|
||||
}
|
||||
|
||||
if (def.type === "intersection") {
|
||||
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
||||
}
|
||||
if (def.type === "record" || def.type === "map") {
|
||||
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
||||
}
|
||||
if (def.type === "pipe") {
|
||||
if (_schema._zod.traits.has("$ZodCodec")) return true;
|
||||
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
||||
}
|
||||
|
||||
if (def.type === "object") {
|
||||
for (const key in def.shape) {
|
||||
if (isTransforming(def.shape[key]!, ctx)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (def.type === "union") {
|
||||
for (const option of def.options) {
|
||||
if (isTransforming(option, ctx)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (def.type === "tuple") {
|
||||
for (const item of def.items) {
|
||||
if (isTransforming(item, ctx)) return true;
|
||||
}
|
||||
if (def.rest && isTransforming(def.rest, ctx)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export type ZodStandardSchemaWithJSON<T> = StandardSchemaWithJSONProps<core.input<T>, core.output<T>>;
|
||||
export interface ZodStandardJSONSchemaPayload<T> extends JSONSchema.BaseSchema {
|
||||
"~standard": ZodStandardSchemaWithJSON<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a toJSONSchema method for a schema instance.
|
||||
* This encapsulates the logic of initializing context, processing, extracting defs, and finalizing.
|
||||
*/
|
||||
export const createToJSONSchemaMethod =
|
||||
<T extends schemas.$ZodType>(schema: T, processors: Record<string, Processor> = {}) =>
|
||||
(params?: ToJSONSchemaParams): ZodStandardJSONSchemaPayload<T> => {
|
||||
const ctx = initializeContext({ ...params, processors });
|
||||
process(schema, ctx);
|
||||
extractDefs(ctx, schema);
|
||||
return finalize(ctx, schema);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a toJSONSchema method for a schema instance.
|
||||
* This encapsulates the logic of initializing context, processing, extracting defs, and finalizing.
|
||||
*/
|
||||
type StandardJSONSchemaMethodParams = Parameters<StandardJSONSchemaV1["~standard"]["jsonSchema"]["input"]>[0];
|
||||
export const createStandardJSONSchemaMethod =
|
||||
<T extends schemas.$ZodType>(schema: T, io: "input" | "output", processors: Record<string, Processor> = {}) =>
|
||||
(params?: StandardJSONSchemaMethodParams): JSONSchema.BaseSchema => {
|
||||
const { libraryOptions, target } = params ?? {};
|
||||
const ctx = initializeContext({ ...(libraryOptions ?? {}), target, io, processors });
|
||||
process(schema, ctx);
|
||||
extractDefs(ctx, schema);
|
||||
return finalize(ctx, schema);
|
||||
};
|
||||
Reference in New Issue
Block a user