WIP: bootstrap and partial real Solana watcher implementation

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

View File

@@ -0,0 +1,80 @@
/**
* @fileoverview Rule to flag use of an lexical declarations inside a case clause
* @author Erik Arvidsson
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Disallow lexical declarations in case clauses",
recommended: true,
url: "https://eslint.org/docs/latest/rules/no-case-declarations",
},
hasSuggestions: true,
schema: [],
messages: {
addBrackets: "Add {} brackets around the case block.",
unexpected: "Unexpected lexical declaration in case block.",
},
},
create(context) {
/**
* Checks whether or not a node is a lexical declaration.
* @param {ASTNode} node A direct child statement of a switch case.
* @returns {boolean} Whether or not the node is a lexical declaration.
*/
function isLexicalDeclaration(node) {
switch (node.type) {
case "FunctionDeclaration":
case "ClassDeclaration":
return true;
case "VariableDeclaration":
return node.kind !== "var";
default:
return false;
}
}
return {
SwitchCase(node) {
for (let i = 0; i < node.consequent.length; i++) {
const statement = node.consequent[i];
if (isLexicalDeclaration(statement)) {
context.report({
node: statement,
messageId: "unexpected",
suggest: [
{
messageId: "addBrackets",
fix: fixer => [
fixer.insertTextBefore(
node.consequent[0],
"{ ",
),
fixer.insertTextAfter(
node.consequent.at(-1),
" }",
),
],
},
],
});
}
}
},
};
},
};

View File

@@ -0,0 +1,5 @@
/// <reference path="./importMeta.d.ts" />
// https://github.com/microsoft/TypeScript/issues/45096
// TypeScript has a bug that makes <reference types="vite/types/importMeta" />
// not possible in userland. This file provides a workaround for now.

View File

@@ -0,0 +1,2 @@
export declare var SyntaxKind: any;
//# sourceMappingURL=syntaxKind.d.ts.map

View File

@@ -0,0 +1 @@
var s=Object.defineProperty;var i=(t,r)=>s(t,"name",{value:r,configurable:!0});import{r as p}from"../../register-C4vWVmug.mjs";import n from"node:crypto";import"../../get-pipe-path-_tAJyU_v.mjs";import{r as c,i as u,c as d}from"../../register-C9AniqUt.mjs";import"../../require-CywAB2e6.mjs";import{i as f,e as g}from"../../node-features-JeyyvQz6.mjs";import"node:module";import"node:worker_threads";import"node:url";import"node:fs";import"node:fs/promises";import"../../index-DQtFPMc2.mjs";import"node:path";import"esbuild";import"node:os";import"../../temporary-directory-BDDVQOvU.mjs";import"../../client-D_mPDF5S.mjs";import"node:net";import"module";import"fs";import"os";import"path";import"node:util";import"../../index-gbaejti9.mjs";const U=i((t,r)=>{if(!r||typeof r=="object"&&!r.parentURL)throw new Error("The current file path (import.meta.url) must be provided in the second argument of tsImport()");const o=typeof r=="string",e=o?r:r.parentURL,m=n.randomUUID(),a=c({namespace:m});return!f(g)&&!u.test(t)&&d.test(t)?Promise.resolve(a.require(t,e)):p({namespace:m,...o?{}:r}).import(t,e)},"tsImport");export{p as register,U as tsImport};

View File

@@ -0,0 +1,42 @@
const fs = require('fs');
const path = require('path');
const flatted = require('flatted');
function tryParse(filePath, defaultValue) {
let result;
try {
result = readJSON(filePath);
} catch (ex) {
result = defaultValue;
}
return result;
}
/**
* Read json file synchronously using flatted
*
* @param {String} filePath Json filepath
* @returns {*} parse result
*/
function readJSON(filePath) {
return flatted.parse(
fs.readFileSync(filePath, {
encoding: 'utf8',
})
);
}
/**
* Write json file synchronously using circular-json
*
* @param {String} filePath Json filepath
* @param {*} data Object to serialize
*/
function writeJSON(filePath, data) {
fs.mkdirSync(path.dirname(filePath), {
recursive: true,
});
fs.writeFileSync(filePath, flatted.stringify(data));
}
module.exports = { tryParse, readJSON, writeJSON };

View File

@@ -0,0 +1,55 @@
export { r as runBaseTests, s as setupEnvironment } from './chunks/base.B6Opl8PE.js';
export { i as init } from './chunks/init.k9zZ9sLh.js';
import 'node:vm';
import '@vitest/spy';
import './chunks/index.DXx9Dtk7.js';
import '@vitest/expect';
import 'node:async_hooks';
import './chunks/setup-common.DYx3LtFI.js';
import './chunks/coverage.CTzCuANN.js';
import '@vitest/snapshot';
import '@vitest/utils/timers';
import './chunks/utils.BX5Fg8C4.js';
import './chunks/rpc.MzXet3jl.js';
import './chunks/index.Chj8NDwU.js';
import './chunks/test.DNmyFkvJ.js';
import '@vitest/runner';
import '@vitest/utils/helpers';
import './chunks/benchmark.CX_oY03V.js';
import '@vitest/runner/utils';
import '@vitest/utils/error';
import 'pathe';
import '@vitest/utils/offset';
import '@vitest/utils/source-map';
import './chunks/_commonjsHelpers.D26ty3Ew.js';
import './chunks/nativeModuleRunner.BIakptoF.js';
import 'node:url';
import './chunks/index.BCY_7LL2.js';
import 'node:fs';
import 'node:module';
import 'node:path';
import 'node:process';
import 'node:fs/promises';
import 'node:assert';
import 'node:v8';
import 'node:util';
import 'vite/module-runner';
import './chunks/traces.DT5aQ62U.js';
import './chunks/evaluatedModules.Dg1zASAC.js';
import './chunks/startVitestModuleRunner.DB-7oCpn.js';
import './chunks/modules.BJuCwlRJ.js';
import './path.js';
import './module-evaluator.js';
import '@vitest/mocker';
import '@vitest/mocker/redirect';
import 'node:perf_hooks';
import './chunks/inspector.CvyFGlXm.js';
import 'node:timers';
import 'node:timers/promises';
import '@vitest/utils/constants';
import './chunks/index.DdgEv5B1.js';
import 'expect-type';
import './chunks/index.DC7d2Pf8.js';
import 'node:console';
import '@vitest/utils/serialize';
import 'tinyrainbow';

View File

@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2015_promise: LibDefinition;

View File

@@ -0,0 +1,5 @@
import assertClassBrand from "./assertClassBrand.js";
function _classPrivateFieldSet2(s, a, r) {
return s.set(assertClassBrand(s, a), r), r;
}
export { _classPrivateFieldSet2 as default };

View File

@@ -0,0 +1 @@
{"version":3,"file":"espree.d.cts","sourceRoot":"","sources":["../espree.cts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,SAAS,MAAM,CAAC"}

View File

@@ -0,0 +1,137 @@
'use strict'
let MapGenerator = require('./map-generator')
let parse = require('./parse')
let Result = require('./result')
let stringify = require('./stringify')
let warnOnce = require('./warn-once')
class NoWorkResult {
get content() {
return this.result.css
}
get css() {
return this.result.css
}
get map() {
return this.result.map
}
get messages() {
return []
}
get opts() {
return this.result.opts
}
get processor() {
return this.result.processor
}
get root() {
if (this._root) {
return this._root
}
let root
let parser = parse
try {
root = parser(this._css, this._opts)
} catch (error) {
this.error = error
}
if (this.error) {
throw this.error
} else {
this._root = root
return root
}
}
get [Symbol.toStringTag]() {
return 'NoWorkResult'
}
constructor(processor, css, opts) {
css = css.toString()
this.stringified = false
this._processor = processor
this._css = css
this._opts = opts
this._map = undefined
let str = stringify
this.result = new Result(this._processor, undefined, this._opts)
this.result.css = css
let self = this
Object.defineProperty(this.result, 'root', {
get() {
return self.root
}
})
let map = new MapGenerator(str, undefined, this._opts, css)
if (map.isMap()) {
let [generatedCSS, generatedMap] = map.generate()
if (generatedCSS) {
this.result.css = generatedCSS
}
if (generatedMap) {
this.result.map = generatedMap
}
} else {
map.clearAnnotation()
this.result.css = map.css
}
}
async() {
if (this.error) return Promise.reject(this.error)
return Promise.resolve(this.result)
}
catch(onRejected) {
return this.async().catch(onRejected)
}
finally(onFinally) {
return this.async().then(onFinally, onFinally)
}
sync() {
if (this.error) throw this.error
return this.result
}
then(onFulfilled, onRejected) {
if (process.env.NODE_ENV !== 'production') {
if (!('from' in this._opts)) {
warnOnce(
'Without `from` option PostCSS could generate wrong source map ' +
'and will not find Browserslist config. Set it to CSS file path ' +
'or to `undefined` to prevent this warning.'
)
}
}
return this.async().then(onFulfilled, onRejected)
}
toString() {
return this._css
}
warnings() {
return []
}
}
module.exports = NoWorkResult
NoWorkResult.default = NoWorkResult

View File

@@ -0,0 +1,352 @@
import { expect, expectTypeOf, test } from "vitest";
import * as z from "zod/mini";
const FAIL = { success: false };
test("z.string", async () => {
const a = z.string();
expect(z.parse(a, "hello")).toEqual("hello");
expect(() => z.parse(a, 123)).toThrow();
expect(() => z.parse(a, false)).toThrow();
type a = z.infer<typeof a>;
expectTypeOf<a>().toEqualTypeOf<string>();
});
// test("z.string with description", () => {
// const a = z.string({ description: "string description" });
// a._def;
// expect(a._def.description).toEqual("string description");
// });
test("z.string with custom error", () => {
const a = z.string({ error: () => "BAD" });
expect(z.safeParse(a, 123).error!.issues[0].message).toEqual("BAD");
});
test("inference in checks", () => {
const a = z.string().check(z.refine((val) => val.length));
z.parse(a, "___");
expect(() => z.parse(a, "")).toThrow();
const b = z.string().check(z.refine((val) => val.length));
z.parse(b, "___");
expect(() => z.parse(b, "")).toThrow();
const c = z.string().check(z.refine((val) => val.length));
z.parse(c, "___");
expect(() => z.parse(c, "")).toThrow();
const d = z.string().check(z.refine((val) => val.length));
z.parse(d, "___");
expect(() => z.parse(d, "")).toThrow();
});
test("z.string async", async () => {
// async
const a = z.string().check(z.refine(async (val) => val.length));
expect(await z.parseAsync(a, "___")).toEqual("___");
await expect(() => z.parseAsync(a, "")).rejects.toThrowError();
});
test("z.uuid", () => {
const a = z.uuid();
// parse uuid
z.parse(a, "550e8400-e29b-41d4-a716-446655440000");
z.parse(a, "550e8400-e29b-61d4-a716-446655440000");
// bad uuid
expect(() => z.parse(a, "hello")).toThrow();
// wrong type
expect(() => z.parse(a, 123)).toThrow();
const b = z.uuidv4();
z.parse(b, "550e8400-e29b-41d4-a716-446655440000");
expect(z.safeParse(b, "550e8400-e29b-61d4-a716-446655440000")).toMatchObject(FAIL);
const c = z.uuidv6();
z.parse(c, "550e8400-e29b-61d4-a716-446655440000");
expect(z.safeParse(c, "550e8400-e29b-41d4-a716-446655440000")).toMatchObject(FAIL);
const d = z.uuidv7();
z.parse(d, "550e8400-e29b-71d4-a716-446655440000");
expect(z.safeParse(d, "550e8400-e29b-41d4-a716-446655440000")).toMatchObject(FAIL);
expect(z.safeParse(d, "550e8400-e29b-61d4-a716-446655440000")).toMatchObject(FAIL);
});
test("z.email", () => {
const a = z.email();
expect(z.parse(a, "test@test.com")).toEqual("test@test.com");
expect(() => z.parse(a, "test")).toThrow();
expect(z.safeParse(a, "bad email", { error: () => "bad email" }).error!.issues[0].message).toEqual("bad email");
const b = z.email("bad email");
expect(z.safeParse(b, "bad email").error!.issues[0].message).toEqual("bad email");
const c = z.email({ error: "bad email" });
expect(z.safeParse(c, "bad email").error!.issues[0].message).toEqual("bad email");
const d = z.email({ error: () => "bad email" });
expect(z.safeParse(d, "bad email").error!.issues[0].message).toEqual("bad email");
});
test("z.url", () => {
const a = z.url();
// valid URLs
expect(a.parse("http://example.com")).toEqual("http://example.com");
expect(a.parse("https://example.com")).toEqual("https://example.com");
expect(a.parse("ftp://example.com")).toEqual("ftp://example.com");
expect(a.parse("http://sub.example.com")).toEqual("http://sub.example.com");
expect(a.parse("https://example.com/path?query=123#fragment")).toEqual("https://example.com/path?query=123#fragment");
expect(a.parse("http://localhost")).toEqual("http://localhost");
expect(a.parse("https://localhost")).toEqual("https://localhost");
expect(a.parse("http://localhost:3000")).toEqual("http://localhost:3000");
expect(a.parse("https://localhost:3000")).toEqual("https://localhost:3000");
// test trimming
expect(a.parse(" http://example.com ")).toEqual("http://example.com");
expect(a.parse(" http://example.com/")).toEqual("http://example.com/");
expect(a.parse(" http://example.com")).toEqual("http://example.com");
expect(a.parse(" http://example.com//")).toEqual("http://example.com//");
// invalid URLs
expect(() => a.parse("not-a-url")).toThrow();
// expect(() => a.parse("http:/example.com")).toThrow();
expect(() => a.parse("://example.com")).toThrow();
expect(() => a.parse("http://")).toThrow();
expect(() => a.parse("example.com")).toThrow();
// wrong type
expect(() => a.parse(123)).toThrow();
expect(() => a.parse(null)).toThrow();
expect(() => a.parse(undefined)).toThrow();
});
test("z.url with optional hostname regex", () => {
const a = z.url({ hostname: /example\.com$/ });
expect(a.parse("http://example.com")).toEqual("http://example.com");
expect(a.parse("https://sub.example.com")).toEqual("https://sub.example.com");
expect(() => a.parse("http://examples.com")).toThrow();
expect(() => a.parse("http://example.org")).toThrow();
expect(() => a.parse("asdf")).toThrow();
});
test("z.url - file urls", () => {
// file URLs
const a = z.url({ hostname: /.*/ }); // allow any hostname
expect(a.parse("file:///path/to/file.txt")).toEqual("file:///path/to/file.txt");
expect(a.parse("file:///C:/path/to/file.txt")).toEqual("file:///C:/path/to/file.txt");
expect(a.parse("file:///C:/path/to/file.txt?query=123#fragment")).toEqual(
"file:///C:/path/to/file.txt?query=123#fragment"
);
});
test("z.url with optional protocol regex", () => {
const a = z.url({ protocol: /^https?$/ });
expect(a.parse("http://example.com")).toEqual("http://example.com");
expect(a.parse("https://example.com")).toEqual("https://example.com");
expect(() => a.parse("ftp://example.com")).toThrow();
expect(() => a.parse("mailto:example@example.com")).toThrow();
expect(() => a.parse("asdf")).toThrow();
});
test("z.url with both hostname and protocol regexes", () => {
const a = z.url({ hostname: /example\.com$/, protocol: /^https$/ });
expect(a.parse("https://example.com")).toEqual("https://example.com");
expect(a.parse("https://sub.example.com")).toEqual("https://sub.example.com");
expect(() => a.parse("http://example.com")).toThrow();
expect(() => a.parse("https://example.org")).toThrow();
expect(() => a.parse("ftp://example.com")).toThrow();
expect(() => a.parse("asdf")).toThrow();
});
test("z.url with invalid regex patterns", () => {
const a = z.url({ hostname: /a+$/, protocol: /^ftp$/ });
a.parse("ftp://a");
a.parse("ftp://aaaaaaaa");
expect(() => a.parse("http://aaa")).toThrow();
expect(() => a.parse("https://example.com")).toThrow();
expect(() => a.parse("ftp://asdfasdf")).toThrow();
expect(() => a.parse("ftp://invalid")).toThrow();
});
test("z.emoji", () => {
const a = z.emoji();
expect(z.parse(a, "😀")).toEqual("😀");
expect(() => z.parse(a, "hello")).toThrow();
});
test("z.nanoid", () => {
const a = z.nanoid();
expect(z.parse(a, "8FHZpIxleEK3axQRBNNjN")).toEqual("8FHZpIxleEK3axQRBNNjN");
expect(() => z.parse(a, "abc")).toThrow();
});
test("z.cuid", () => {
const a = z.cuid();
expect(z.parse(a, "cixs7y0c0000f7x3b1z6m3w6r")).toEqual("cixs7y0c0000f7x3b1z6m3w6r");
expect(() => z.parse(a, "abc")).toThrow();
});
test("z.cuid2", () => {
const a = z.cuid2();
expect(z.parse(a, "cixs7y0c0000f7x3b1z6m3w6r")).toEqual("cixs7y0c0000f7x3b1z6m3w6r");
expect(() => z.parse(a, 123)).toThrow();
});
test("z.ulid", () => {
const a = z.ulid();
expect(z.parse(a, "01ETGRM9QYVX6S9V2F3B6JXG4N")).toEqual("01ETGRM9QYVX6S9V2F3B6JXG4N");
expect(() => z.parse(a, "abc")).toThrow();
});
test("z.xid", () => {
const a = z.xid();
expect(z.parse(a, "9m4e2mr0ui3e8a215n4g")).toEqual("9m4e2mr0ui3e8a215n4g");
expect(() => z.parse(a, "abc")).toThrow();
});
test("z.ksuid", () => {
const a = z.ksuid();
expect(z.parse(a, "2naeRjTrrHJAkfd3tOuEjw90WCA")).toEqual("2naeRjTrrHJAkfd3tOuEjw90WCA");
expect(() => z.parse(a, "abc")).toThrow();
});
// test("z.ip", () => {
// const a = z.ip();
// expect(z.parse(a, "127.0.0.1")).toEqual("127.0.0.1");
// expect(z.parse(a, "2001:0db8:85a3:0000:0000:8a2e:0370:7334")).toEqual("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
// expect(() => z.parse(a, "abc")).toThrow();
// });
test("z.ipv4", () => {
const a = z.ipv4();
// valid ipv4
expect(z.parse(a, "192.168.1.1")).toEqual("192.168.1.1");
expect(z.parse(a, "255.255.255.255")).toEqual("255.255.255.255");
// invalid ipv4
expect(() => z.parse(a, "999.999.999.999")).toThrow();
expect(() => z.parse(a, "256.256.256.256")).toThrow();
expect(() => z.parse(a, "192.168.1")).toThrow();
expect(() => z.parse(a, "hello")).toThrow();
// wrong type
expect(() => z.parse(a, 123)).toThrow();
});
test("z.ipv6", () => {
const a = z.ipv6();
// valid ipv6
expect(z.parse(a, "2001:0db8:85a3:0000:0000:8a2e:0370:7334")).toEqual("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
expect(z.parse(a, "::1")).toEqual("::1");
// invalid ipv6
expect(() => z.parse(a, "2001:db8::85a3::8a2e:370:7334")).toThrow();
expect(() => z.parse(a, "2001:db8:85a3:0:0:8a2e:370g:7334")).toThrow();
expect(() => z.parse(a, "hello")).toThrow();
// wrong type
expect(() => z.parse(a, 123)).toThrow();
});
test("z.mac", () => {
const a = z.mac();
// valid mac
expect(z.parse(a, "00:1A:2B:3C:4D:5E")).toEqual("00:1A:2B:3C:4D:5E");
// invalid mac (dash delimiter not accepted by default)
expect(() => z.parse(a, "01-23-45-67-89-AB")).toThrow();
expect(() => z.parse(a, "00:1A:2B::4D:5E")).toThrow();
expect(() => z.parse(a, "00:1a-2B:3c-4D:5e")).toThrow();
expect(() => z.parse(a, "hello")).toThrow();
// wrong type
expect(() => z.parse(a, 123)).toThrow();
});
test("z.mac with custom delimiter", () => {
const a = z.mac({ delimiter: ":" });
// valid mac with colon
expect(z.parse(a, "00:1A:2B:3C:4D:5E")).toEqual("00:1A:2B:3C:4D:5E");
// invalid mac with dash
expect(() => z.parse(a, "00-1A-2B-3C-4D-5E")).toThrow();
const b = z.mac({ delimiter: "-" });
// valid mac with dash
expect(z.parse(b, "00-1A-2B-3C-4D-5E")).toEqual("00-1A-2B-3C-4D-5E");
// invalid mac with colon
expect(() => z.parse(b, "00:1A:2B:3C:4D:5E")).toThrow();
const c = z.mac({ delimiter: ":" });
// colon-only mac
expect(z.parse(c, "00:1A:2B:3C:4D:5E")).toEqual("00:1A:2B:3C:4D:5E");
expect(() => z.parse(c, "00-1A-2B-3C-4D-5E")).toThrow();
});
test("z.base64", () => {
const a = z.base64();
// valid base64
expect(z.parse(a, "SGVsbG8gd29ybGQ=")).toEqual("SGVsbG8gd29ybGQ=");
expect(z.parse(a, "U29tZSBvdGhlciBzdHJpbmc=")).toEqual("U29tZSBvdGhlciBzdHJpbmc=");
// invalid base64
expect(() => z.parse(a, "SGVsbG8gd29ybGQ")).toThrow();
expect(() => z.parse(a, "U29tZSBvdGhlciBzdHJpbmc")).toThrow();
expect(() => z.parse(a, "hello")).toThrow();
// whitespace is not allowed (atob would otherwise strip it)
expect(() => z.parse(a, "123 ")).toThrow();
expect(() => z.parse(a, "SGVsbG8gd29ybGQ= ")).toThrow();
expect(() => z.parse(a, "SGVsbG8gd29ybGQ=\n")).toThrow();
expect(() => z.parse(a, "SGVs bG8gd29ybGQ=")).toThrow();
// wrong type
expect(() => z.parse(a, 123)).toThrow();
});
// test("z.jsonString", () => {
// const a = z.jsonString();
// // valid JSON string
// expect(z.parse(a, '{"key":"value"}')).toEqual('{"key":"value"}');
// expect(z.parse(a, '["item1", "item2"]')).toEqual('["item1", "item2"]');
// // invalid JSON string
// expect(() => z.parse(a, '{"key":value}')).toThrow();
// expect(() => z.parse(a, '["item1", "item2"')).toThrow();
// expect(() => z.parse(a, "hello")).toThrow();
// // wrong type
// expect(() => z.parse(a, 123)).toThrow();
// });
test("z.e164", () => {
const a = z.e164();
// valid e164
expect(z.parse(a, "+1234567890")).toEqual("+1234567890");
expect(z.parse(a, "+19876543210")).toEqual("+19876543210");
// invalid e164
expect(() => z.parse(a, "1234567890")).toThrow();
expect(() => z.parse(a, "+12345")).toThrow();
expect(() => z.parse(a, "hello")).toThrow();
// wrong type
expect(() => z.parse(a, 123)).toThrow();
});
test("z.jwt", () => {
const a = z.jwt();
// valid jwt
expect(
z.parse(
a,
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
)
).toEqual(
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
);
// invalid jwt
expect(() => z.parse(a, "invalid.jwt.token")).toThrow();
expect(() => z.parse(a, "hello")).toThrow();
// wrong type
expect(() => z.parse(a, 123)).toThrow();
});
test("z.hash generic format", () => {
expect(z.hash("sha256").parse("a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3")).toBe(
"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"
);
// --- Type-level checks (ensure the literal format string is encoded in the return type)
expectTypeOf(z.hash("md5")).toEqualTypeOf<z.ZodMiniCustomStringFormat<"md5_hex">>();
expectTypeOf(z.hash("sha1")).toEqualTypeOf<z.ZodMiniCustomStringFormat<"sha1_hex">>();
expectTypeOf(z.hash("sha256", { enc: "base64" as const })).toEqualTypeOf<
z.ZodMiniCustomStringFormat<"sha256_base64">
>();
expectTypeOf(z.hash("sha384", { enc: "base64url" as const })).toEqualTypeOf<
z.ZodMiniCustomStringFormat<"sha384_base64url">
>();
});

View File

@@ -0,0 +1,128 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// SEE https://typescript-eslint.io/users/configs
//
// For developers working in the typescript-eslint monorepo:
// You can regenerate it using `pnpm run generate-configs`
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const base_1 = __importDefault(require("./base"));
const eslint_recommended_1 = __importDefault(require("./eslint-recommended"));
/**
* Contains all of `recommended`, `recommended-type-checked`, and `strict`, along with additional strict rules that require type information.
* @see {@link https://typescript-eslint.io/users/configs#strict-type-checked}
*/
exports.default = (plugin, parser) => [
(0, base_1.default)(plugin, parser),
(0, eslint_recommended_1.default)(plugin, parser),
{
name: 'typescript-eslint/strict-type-checked',
rules: {
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/ban-ts-comment': [
'error',
{ minimumDescriptionLength: 10 },
],
'no-array-constructor': 'off',
'@typescript-eslint/no-array-constructor': 'error',
'@typescript-eslint/no-array-delete': 'error',
'@typescript-eslint/no-base-to-string': 'error',
'@typescript-eslint/no-confusing-void-expression': 'error',
'@typescript-eslint/no-deprecated': 'error',
'@typescript-eslint/no-duplicate-enum-values': 'error',
'@typescript-eslint/no-duplicate-type-constituents': 'error',
'@typescript-eslint/no-dynamic-delete': 'error',
'@typescript-eslint/no-empty-object-type': 'error',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-extra-non-null-assertion': 'error',
'@typescript-eslint/no-extraneous-class': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-for-in-array': 'error',
'no-implied-eval': 'off',
'@typescript-eslint/no-implied-eval': 'error',
'@typescript-eslint/no-invalid-void-type': 'error',
'@typescript-eslint/no-meaningless-void-operator': 'error',
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/no-misused-spread': 'error',
'@typescript-eslint/no-mixed-enums': 'error',
'@typescript-eslint/no-namespace': 'error',
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-redundant-type-constituents': 'error',
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-this-alias': 'error',
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
'@typescript-eslint/no-unnecessary-condition': 'error',
'@typescript-eslint/no-unnecessary-template-expression': 'error',
'@typescript-eslint/no-unnecessary-type-arguments': 'error',
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
'@typescript-eslint/no-unnecessary-type-constraint': 'error',
'@typescript-eslint/no-unnecessary-type-conversion': 'error',
'@typescript-eslint/no-unnecessary-type-parameters': 'error',
'@typescript-eslint/no-unsafe-argument': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-declaration-merging': 'error',
'@typescript-eslint/no-unsafe-enum-comparison': 'error',
'@typescript-eslint/no-unsafe-function-type': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
'@typescript-eslint/no-unsafe-unary-minus': 'error',
'no-unused-expressions': 'off',
'@typescript-eslint/no-unused-expressions': 'error',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'error',
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': 'error',
'@typescript-eslint/no-useless-default-assignment': 'error',
'@typescript-eslint/no-wrapper-object-types': 'error',
'no-throw-literal': 'off',
'@typescript-eslint/only-throw-error': 'error',
'@typescript-eslint/prefer-as-const': 'error',
'@typescript-eslint/prefer-literal-enum-member': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
'prefer-promise-reject-errors': 'off',
'@typescript-eslint/prefer-promise-reject-errors': 'error',
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
'@typescript-eslint/prefer-return-this-type': 'error',
'@typescript-eslint/related-getter-setter-pairs': 'error',
'require-await': 'off',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/restrict-plus-operands': [
'error',
{
allowAny: false,
allowBoolean: false,
allowNullish: false,
allowNumberAndString: false,
allowRegExp: false,
},
],
'@typescript-eslint/restrict-template-expressions': [
'error',
{
allowAny: false,
allowBoolean: false,
allowNever: false,
allowNullish: false,
allowNumber: false,
allowRegExp: false,
},
],
'no-return-await': 'off',
'@typescript-eslint/return-await': [
'error',
'error-handling-correctness-only',
],
'@typescript-eslint/triple-slash-reference': 'error',
'@typescript-eslint/unbound-method': 'error',
'@typescript-eslint/unified-signatures': 'error',
'@typescript-eslint/use-unknown-in-catch-callback-variable': 'error',
},
},
];

View File

@@ -0,0 +1,3 @@
"use strict";
exports._ = require("tslib").__addDisposableResource;

View File

@@ -0,0 +1,4 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noExtraNonNullAssertion", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
name: string;
};
export default _default;

View File

@@ -0,0 +1 @@
{"version":3,"file":"wtf8.js","sourceRoot":"","sources":["../../../src/api/node/wtf8.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACpC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACpC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACjC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAGjC,SAAS,eAAe,CAAC,KAAiB,EAAE,KAAa;IACrD,OAAO,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM;WACxB,KAAK,CAAC,KAAK,CAAC,KAAK,iBAAiB;WAClC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,sBAAsB;WAC1C,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,sBAAsB;WAC1C,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,mBAAmB;WACvC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,mBAAmB,CAAC;AACnD,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAiB,EAAE,KAAa;IAC1D,OAAO,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAiB;IAC3C,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACzG,CAAC;AAED,SAAS,YAAY,CAAC,KAAqC;IACvD,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,OAAO,WAAY,SAAQ,WAAW;IAC/B,MAAM,CAAC,KAAsC,EAAE,OAAuB;QAC3E,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,YAAY,GAAG,CAAC,CAAC;QAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC7B,SAAS;YACb,CAAC;YAED,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;gBACnB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YACvE,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAChE,CAAC,IAAI,CAAC,CAAC;YACP,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAED,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,YAAY,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;CACJ"}

View File

@@ -0,0 +1,833 @@
"use strict";
// This rule was feature-frozen before we enabled no-property-in-node.
/* eslint-disable eslint-plugin/no-property-in-node */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultOrder = void 0;
const utils_1 = require("@typescript-eslint/utils");
const natural_compare_1 = __importDefault(require("natural-compare"));
const util_1 = require("../util");
const neverConfig = {
type: 'string',
enum: ['never'],
};
const arrayConfig = (memberTypes) => ({
type: 'array',
items: {
oneOf: [
{
$ref: memberTypes,
},
{
type: 'array',
items: {
$ref: memberTypes,
},
},
],
},
});
const objectConfig = (memberTypes) => ({
type: 'object',
additionalProperties: false,
properties: {
memberTypes: {
oneOf: [arrayConfig(memberTypes), neverConfig],
},
optionalityOrder: {
$ref: '#/items/0/$defs/optionalityOrderOptions',
},
order: {
$ref: '#/items/0/$defs/orderOptions',
},
},
});
exports.defaultOrder = [
// Index signature
'signature',
'call-signature',
// Fields
'public-static-field',
'protected-static-field',
'private-static-field',
'#private-static-field',
'public-decorated-field',
'protected-decorated-field',
'private-decorated-field',
'public-instance-field',
'protected-instance-field',
'private-instance-field',
'#private-instance-field',
'public-abstract-field',
'protected-abstract-field',
'public-field',
'protected-field',
'private-field',
'#private-field',
'static-field',
'instance-field',
'abstract-field',
'decorated-field',
'field',
// Static initialization
'static-initialization',
// Constructors
'public-constructor',
'protected-constructor',
'private-constructor',
'constructor',
// Accessors
'public-static-accessor',
'protected-static-accessor',
'private-static-accessor',
'#private-static-accessor',
'public-decorated-accessor',
'protected-decorated-accessor',
'private-decorated-accessor',
'public-instance-accessor',
'protected-instance-accessor',
'private-instance-accessor',
'#private-instance-accessor',
'public-abstract-accessor',
'protected-abstract-accessor',
'public-accessor',
'protected-accessor',
'private-accessor',
'#private-accessor',
'static-accessor',
'instance-accessor',
'abstract-accessor',
'decorated-accessor',
'accessor',
// Getters
'public-static-get',
'protected-static-get',
'private-static-get',
'#private-static-get',
'public-decorated-get',
'protected-decorated-get',
'private-decorated-get',
'public-instance-get',
'protected-instance-get',
'private-instance-get',
'#private-instance-get',
'public-abstract-get',
'protected-abstract-get',
'public-get',
'protected-get',
'private-get',
'#private-get',
'static-get',
'instance-get',
'abstract-get',
'decorated-get',
'get',
// Setters
'public-static-set',
'protected-static-set',
'private-static-set',
'#private-static-set',
'public-decorated-set',
'protected-decorated-set',
'private-decorated-set',
'public-instance-set',
'protected-instance-set',
'private-instance-set',
'#private-instance-set',
'public-abstract-set',
'protected-abstract-set',
'public-set',
'protected-set',
'private-set',
'#private-set',
'static-set',
'instance-set',
'abstract-set',
'decorated-set',
'set',
// Methods
'public-static-method',
'protected-static-method',
'private-static-method',
'#private-static-method',
'public-decorated-method',
'protected-decorated-method',
'private-decorated-method',
'public-instance-method',
'protected-instance-method',
'private-instance-method',
'#private-instance-method',
'public-abstract-method',
'protected-abstract-method',
'public-method',
'protected-method',
'private-method',
'#private-method',
'static-method',
'instance-method',
'abstract-method',
'decorated-method',
'method',
];
const allMemberTypes = [
...new Set([
'readonly-signature',
'signature',
'readonly-field',
'field',
'method',
'call-signature',
'constructor',
'accessor',
'get',
'set',
'static-initialization',
].flatMap(type => [
type,
...['public', 'protected', 'private', '#private']
.flatMap(accessibility => [
type !== 'readonly-signature' &&
type !== 'signature' &&
type !== 'static-initialization' &&
type !== 'call-signature' &&
!(type === 'constructor' && accessibility === '#private')
? `${accessibility}-${type}` // e.g. `public-field`
: [],
// Only class instance fields, methods, accessors, get and set can have decorators attached to them
accessibility !== '#private' &&
(type === 'readonly-field' ||
type === 'field' ||
type === 'method' ||
type === 'accessor' ||
type === 'get' ||
type === 'set')
? [`${accessibility}-decorated-${type}`, `decorated-${type}`]
: [],
type !== 'constructor' &&
type !== 'readonly-signature' &&
type !== 'signature' &&
type !== 'call-signature'
? [
'static',
'instance',
// There is no `static-constructor` or `instance-constructor` or `abstract-constructor`
...(accessibility === '#private' ||
accessibility === 'private'
? []
: ['abstract']),
].flatMap(scope => [
`${scope}-${type}`,
`${accessibility}-${scope}-${type}`,
])
: [],
])
.flat(),
])),
];
const functionExpressions = [
utils_1.AST_NODE_TYPES.FunctionExpression,
utils_1.AST_NODE_TYPES.ArrowFunctionExpression,
];
/**
* Gets the node type.
*
* @param node the node to be evaluated.
*/
function getNodeType(node) {
switch (node.type) {
case utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition:
case utils_1.AST_NODE_TYPES.MethodDefinition:
case utils_1.AST_NODE_TYPES.TSMethodSignature:
return node.kind;
case utils_1.AST_NODE_TYPES.TSCallSignatureDeclaration:
return 'call-signature';
case utils_1.AST_NODE_TYPES.TSConstructSignatureDeclaration:
return 'constructor';
case utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition:
case utils_1.AST_NODE_TYPES.TSPropertySignature:
return node.readonly ? 'readonly-field' : 'field';
case utils_1.AST_NODE_TYPES.TSAbstractAccessorProperty:
case utils_1.AST_NODE_TYPES.AccessorProperty:
return 'accessor';
case utils_1.AST_NODE_TYPES.PropertyDefinition:
return node.value && functionExpressions.includes(node.value.type)
? 'method'
: node.readonly
? 'readonly-field'
: 'field';
case utils_1.AST_NODE_TYPES.TSIndexSignature:
return node.readonly ? 'readonly-signature' : 'signature';
case utils_1.AST_NODE_TYPES.StaticBlock:
return 'static-initialization';
default:
return null;
}
}
/**
* Gets the raw string value of a member's name
*/
function getMemberRawName(member, sourceCode) {
const { name, type } = (0, util_1.getNameFromMember)(member, sourceCode);
if (type === util_1.MemberNameType.Quoted) {
return name.slice(1, -1);
}
if (type === util_1.MemberNameType.Private) {
return name.slice(1);
}
return name;
}
/**
* Gets the member name based on the member type.
*
* @param node the node to be evaluated.
*/
function getMemberName(node, sourceCode) {
switch (node.type) {
case utils_1.AST_NODE_TYPES.TSPropertySignature:
case utils_1.AST_NODE_TYPES.TSMethodSignature:
case utils_1.AST_NODE_TYPES.TSAbstractAccessorProperty:
case utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition:
case utils_1.AST_NODE_TYPES.AccessorProperty:
case utils_1.AST_NODE_TYPES.PropertyDefinition:
return getMemberRawName(node, sourceCode);
case utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition:
case utils_1.AST_NODE_TYPES.MethodDefinition:
return node.kind === 'constructor'
? 'constructor'
: getMemberRawName(node, sourceCode);
case utils_1.AST_NODE_TYPES.TSConstructSignatureDeclaration:
return 'new';
case utils_1.AST_NODE_TYPES.TSCallSignatureDeclaration:
return 'call';
case utils_1.AST_NODE_TYPES.TSIndexSignature:
return (0, util_1.getNameFromIndexSignature)(node);
case utils_1.AST_NODE_TYPES.StaticBlock:
return 'static block';
default:
return null;
}
}
/**
* Returns true if the member is optional based on the member type.
*
* @param node the node to be evaluated.
*
* @returns Whether the member is optional, or false if it cannot be optional at all.
*/
function isMemberOptional(node) {
switch (node.type) {
case utils_1.AST_NODE_TYPES.TSPropertySignature:
case utils_1.AST_NODE_TYPES.TSMethodSignature:
case utils_1.AST_NODE_TYPES.TSAbstractAccessorProperty:
case utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition:
case utils_1.AST_NODE_TYPES.AccessorProperty:
case utils_1.AST_NODE_TYPES.PropertyDefinition:
case utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition:
case utils_1.AST_NODE_TYPES.MethodDefinition:
return node.optional;
}
return false;
}
/**
* Gets the calculated rank using the provided method definition.
* The algorithm is as follows:
* - Get the rank based on the accessibility-scope-type name, e.g. public-instance-field
* - If there is no order for accessibility-scope-type, then strip out the accessibility.
* - If there is no order for scope-type, then strip out the scope.
* - If there is no order for type, then return -1
* @param memberGroups the valid names to be validated.
* @param orderConfig the current order to be validated.
*
* @return Index of the matching member type in the order configuration.
*/
function getRankOrder(memberGroups, orderConfig) {
let rank = -1;
const stack = [...memberGroups]; // Get a copy of the member groups
while (stack.length > 0 && rank === -1) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const memberGroup = stack.shift();
rank = orderConfig.findIndex(memberType => Array.isArray(memberType)
? memberType.includes(memberGroup)
: memberType === memberGroup);
}
return rank;
}
function getAccessibility(node) {
if ('accessibility' in node && node.accessibility) {
return node.accessibility;
}
if ('key' in node && node.key.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
return '#private';
}
return 'public';
}
/**
* Gets the rank of the node given the order.
* @param node the node to be evaluated.
* @param orderConfig the current order to be validated.
* @param supportsModifiers a flag indicating whether the type supports modifiers (scope or accessibility) or not.
*/
function getRank(node, orderConfig, supportsModifiers) {
const type = getNodeType(node);
if (node.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
node.value.type === utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression) {
return -1;
}
if (type == null) {
// shouldn't happen but just in case, put it on the end
return orderConfig.length - 1;
}
const abstract = node.type === utils_1.AST_NODE_TYPES.TSAbstractAccessorProperty ||
node.type === utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition ||
node.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition;
const scope = 'static' in node && node.static
? 'static'
: abstract
? 'abstract'
: 'instance';
const accessibility = getAccessibility(node);
// Collect all existing member groups that apply to this node...
// (e.g. 'public-instance-field', 'instance-field', 'public-field', 'constructor' etc.)
const memberGroups = [];
if (supportsModifiers) {
const decorated = 'decorators' in node && node.decorators.length > 0;
if (decorated &&
(type === 'readonly-field' ||
type === 'field' ||
type === 'method' ||
type === 'accessor' ||
type === 'get' ||
type === 'set')) {
memberGroups.push(`${accessibility}-decorated-${type}`);
memberGroups.push(`decorated-${type}`);
if (type === 'readonly-field') {
memberGroups.push(`${accessibility}-decorated-field`);
memberGroups.push(`decorated-field`);
}
}
if (type !== 'readonly-signature' &&
type !== 'signature' &&
type !== 'static-initialization') {
if (type !== 'constructor') {
// Constructors have no scope
memberGroups.push(`${accessibility}-${scope}-${type}`);
memberGroups.push(`${scope}-${type}`);
if (type === 'readonly-field') {
memberGroups.push(`${accessibility}-${scope}-field`);
memberGroups.push(`${scope}-field`);
}
}
memberGroups.push(`${accessibility}-${type}`);
if (type === 'readonly-field') {
memberGroups.push(`${accessibility}-field`);
}
}
}
memberGroups.push(type);
if (type === 'readonly-signature') {
memberGroups.push('signature');
}
else if (type === 'readonly-field') {
memberGroups.push('field');
}
// ...then get the rank order for those member groups based on the node
return getRankOrder(memberGroups, orderConfig);
}
/**
* Groups members into arrays of consecutive members with the same rank.
* If, for example, the memberSet parameter looks like the following...
* @example
* ```
* interface Foo {
* [a: string]: number;
*
* a: x;
* B: x;
* c: x;
*
* c(): void;
* B(): void;
* a(): void;
*
* (): Baz;
*
* new (): Bar;
* }
* ```
* ...the resulting array will look like: [[a, B, c], [c, B, a]].
* @param memberSet The members to be grouped.
* @param memberType The configured order of member types.
* @param supportsModifiers It'll get passed to getRank().
* @returns The array of groups of members.
*/
function groupMembersByType(members, memberTypes, supportsModifiers) {
const groupedMembers = [];
const memberRanks = members.map(member => getRank(member, memberTypes, supportsModifiers));
let previousRank = undefined;
members.forEach((member, index) => {
if (index === members.length - 1) {
return;
}
const rankOfCurrentMember = memberRanks[index];
const rankOfNextMember = memberRanks[index + 1];
if (rankOfCurrentMember === previousRank) {
groupedMembers.at(-1)?.push(member);
}
else if (rankOfCurrentMember === rankOfNextMember) {
groupedMembers.push([member]);
previousRank = rankOfCurrentMember;
}
});
return groupedMembers;
}
/**
* Gets the lowest possible rank(s) higher than target.
* e.g. given the following order:
* ...
* public-static-method
* protected-static-method
* private-static-method
* public-instance-method
* protected-instance-method
* private-instance-method
* ...
* and considering that a public-instance-method has already been declared, so ranks contains
* public-instance-method, then the lowest possible rank for public-static-method is
* public-instance-method.
* If a lowest possible rank is a member group, a comma separated list of ranks is returned.
* @param ranks the existing ranks in the object.
* @param target the minimum target rank to filter on.
* @param order the current order to be validated.
* @returns the name(s) of the lowest possible rank without dashes (-).
*/
function getLowestRank(ranks, target, order) {
let lowest = ranks[ranks.length - 1];
ranks.forEach(rank => {
if (rank > target) {
lowest = Math.min(lowest, rank);
}
});
const lowestRank = order[lowest];
const lowestRanks = Array.isArray(lowestRank) ? lowestRank : [lowestRank];
return lowestRanks.map(rank => rank.replaceAll('-', ' ')).join(', ');
}
exports.default = (0, util_1.createRule)({
name: 'member-ordering',
meta: {
type: 'suggestion',
docs: {
description: 'Require a consistent member declaration order',
frozen: true,
},
messages: {
incorrectGroupOrder: 'Member {{name}} should be declared before all {{rank}} definitions.',
incorrectOrder: 'Member {{member}} should be declared before member {{beforeMember}}.',
incorrectRequiredMembersOrder: `Member {{member}} should be declared after all {{optionalOrRequired}} members.`,
},
schema: [
{
type: 'object',
$defs: {
allItems: {
type: 'string',
enum: allMemberTypes,
},
optionalityOrderOptions: {
type: 'string',
enum: ['optional-first', 'required-first'],
},
orderOptions: {
type: 'string',
enum: [
'alphabetically',
'alphabetically-case-insensitive',
'as-written',
'natural',
'natural-case-insensitive',
],
},
typeItems: {
type: 'string',
enum: [
'readonly-signature',
'signature',
'readonly-field',
'field',
'method',
'constructor',
],
},
// ajv is order-dependent; these configs must come last
baseConfig: {
oneOf: [
neverConfig,
arrayConfig('#/items/0/$defs/allItems'),
objectConfig('#/items/0/$defs/allItems'),
],
},
typesConfig: {
oneOf: [
neverConfig,
arrayConfig('#/items/0/$defs/typeItems'),
objectConfig('#/items/0/$defs/typeItems'),
],
},
},
additionalProperties: false,
properties: {
classes: {
$ref: '#/items/0/$defs/baseConfig',
description: 'Which ordering to enforce for classes.',
},
classExpressions: {
$ref: '#/items/0/$defs/baseConfig',
description: 'Which ordering to enforce for classExpressions.',
},
default: {
$ref: '#/items/0/$defs/baseConfig',
description: 'Which ordering to enforce for default.',
},
interfaces: {
$ref: '#/items/0/$defs/typesConfig',
description: 'Which ordering to enforce for interfaces.',
},
typeLiterals: {
$ref: '#/items/0/$defs/typesConfig',
description: 'Which ordering to enforce for typeLiterals.',
},
},
},
],
},
defaultOptions: [
{
default: {
memberTypes: exports.defaultOrder,
},
},
],
create(context, [options]) {
/**
* Checks if the member groups are correctly sorted.
*
* @param members Members to be validated.
* @param groupOrder Group order to be validated.
* @param supportsModifiers A flag indicating whether the type supports modifiers (scope or accessibility) or not.
*
* @return Array of member groups or null if one of the groups is not correctly sorted.
*/
function checkGroupSort(members, groupOrder, supportsModifiers) {
const previousRanks = [];
const memberGroups = [];
let isCorrectlySorted = true;
// Find first member which isn't correctly sorted
for (const member of members) {
const rank = getRank(member, groupOrder, supportsModifiers);
const name = getMemberName(member, context.sourceCode);
const rankLastMember = previousRanks[previousRanks.length - 1];
if (rank === -1) {
continue;
}
// Works for 1st item because x < undefined === false for any x (typeof string)
if (rank < rankLastMember) {
context.report({
node: member,
messageId: 'incorrectGroupOrder',
data: {
name,
rank: getLowestRank(previousRanks, rank, groupOrder),
},
});
isCorrectlySorted = false;
}
else if (rank === rankLastMember) {
// Same member group --> Push to existing member group array
memberGroups[memberGroups.length - 1].push(member);
}
else {
// New member group --> Create new member group array
previousRanks.push(rank);
memberGroups.push([member]);
}
}
return isCorrectlySorted ? memberGroups : null;
}
/**
* Checks if the members are alphabetically sorted.
*
* @param members Members to be validated.
* @param order What order the members should be sorted in.
*
* @return True if all members are correctly sorted.
*/
function checkAlphaSort(members, order) {
let previousName = '';
let isCorrectlySorted = true;
// Find first member which isn't correctly sorted
members.forEach(member => {
const name = getMemberName(member, context.sourceCode);
// Note: Not all members have names
if (name) {
if (naturalOutOfOrder(name, previousName, order)) {
context.report({
node: member,
messageId: 'incorrectOrder',
data: {
beforeMember: previousName,
member: name,
},
});
isCorrectlySorted = false;
}
previousName = name;
}
});
return isCorrectlySorted;
}
function naturalOutOfOrder(name, previousName, order) {
if (name === previousName) {
return false;
}
switch (order) {
case 'alphabetically':
return name < previousName;
case 'alphabetically-case-insensitive':
return name.toLowerCase() < previousName.toLowerCase();
case 'natural':
return (0, natural_compare_1.default)(name, previousName) !== 1;
case 'natural-case-insensitive':
return ((0, natural_compare_1.default)(name.toLowerCase(), previousName.toLowerCase()) !== 1);
}
}
/**
* Checks if the order of optional and required members is correct based
* on the given 'required' parameter.
*
* @param members Members to be validated.
* @param optionalityOrder Where to place optional members, if not intermixed.
*
* @return True if all required and optional members are correctly sorted.
*/
function checkRequiredOrder(members, optionalityOrder) {
const switchIndex = members.findIndex((member, i) => i && isMemberOptional(member) !== isMemberOptional(members[i - 1]));
const report = (member) => context.report({
loc: member.loc,
messageId: 'incorrectRequiredMembersOrder',
data: {
member: getMemberName(member, context.sourceCode),
optionalOrRequired: optionalityOrder === 'required-first' ? 'required' : 'optional',
},
});
// if the optionality of the first item is correct (based on optionalityOrder)
// then the first 0 inclusive to switchIndex exclusive members all
// have the correct optionality
if (isMemberOptional(members[0]) !==
(optionalityOrder === 'optional-first')) {
report(members[0]);
return false;
}
for (let i = switchIndex + 1; i < members.length; i++) {
if (isMemberOptional(members[i]) !==
isMemberOptional(members[switchIndex])) {
report(members[switchIndex]);
return false;
}
}
return true;
}
/**
* Validates if all members are correctly sorted.
*
* @param members Members to be validated.
* @param orderConfig Order config to be validated.
* @param supportsModifiers A flag indicating whether the type supports modifiers (scope or accessibility) or not.
*/
function validateMembersOrder(members, orderConfig, supportsModifiers) {
if (orderConfig === 'never') {
return;
}
// Standardize config
let order;
let memberTypes;
let optionalityOrder;
/**
* It runs an alphabetic sort on the groups of the members of the class in the source code.
* @param memberSet The members in the class of the source code on which the grouping operation will be performed.
*/
const checkAlphaSortForAllMembers = (memberSet) => {
const hasAlphaSort = !!(order && order !== 'as-written');
if (hasAlphaSort && Array.isArray(memberTypes)) {
groupMembersByType(memberSet, memberTypes, supportsModifiers).forEach(members => {
checkAlphaSort(members, order);
});
}
};
// returns true if everything is good and false if an error was reported
const checkOrder = (memberSet) => {
const hasAlphaSort = !!(order && order !== 'as-written');
// Check order
if (Array.isArray(memberTypes)) {
const grouped = checkGroupSort(memberSet, memberTypes, supportsModifiers);
if (grouped == null) {
checkAlphaSortForAllMembers(members);
return false;
}
if (hasAlphaSort) {
grouped.map(groupMember => checkAlphaSort(groupMember, order));
}
}
else if (hasAlphaSort) {
return checkAlphaSort(memberSet, order);
}
return false;
};
if (Array.isArray(orderConfig)) {
memberTypes = orderConfig;
}
else {
order = orderConfig.order;
memberTypes = orderConfig.memberTypes;
optionalityOrder = orderConfig.optionalityOrder;
}
if (!optionalityOrder) {
checkOrder(members);
return;
}
const switchIndex = members.findIndex((member, i) => i && isMemberOptional(member) !== isMemberOptional(members[i - 1]));
if (switchIndex !== -1) {
if (!checkRequiredOrder(members, optionalityOrder)) {
return;
}
checkOrder(members.slice(0, switchIndex));
checkOrder(members.slice(switchIndex));
}
else {
checkOrder(members);
}
}
// https://github.com/typescript-eslint/typescript-eslint/issues/5439
/* eslint-disable @typescript-eslint/no-non-null-assertion */
return {
ClassDeclaration(node) {
validateMembersOrder(node.body.body, options.classes ?? options.default, true);
},
'ClassDeclaration, FunctionDeclaration'(node) {
if ('superClass' in node) {
// ...
}
},
ClassExpression(node) {
validateMembersOrder(node.body.body, options.classExpressions ?? options.default, true);
},
TSInterfaceDeclaration(node) {
validateMembersOrder(node.body.body, options.interfaces ?? options.default, false);
},
TSTypeLiteral(node) {
validateMembersOrder(node.members, options.typeLiterals ?? options.default, false);
},
};
/* eslint-enable @typescript-eslint/no-non-null-assertion */
},
});

View File

@@ -0,0 +1,77 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2015.iterable" />
interface Generator<T = unknown, TReturn = any, TNext = unknown> extends Iterator<T, TReturn, TNext> {
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
return(value: TReturn): IteratorResult<T, TReturn>;
throw(e: any): IteratorResult<T, TReturn>;
[Symbol.iterator](): Generator<T, TReturn, TNext>;
}
interface GeneratorFunction {
/**
* Creates a new Generator object.
* @param args A list of arguments the function accepts.
*/
new (...args: any[]): Generator;
/**
* Creates a new Generator object.
* @param args A list of arguments the function accepts.
*/
(...args: any[]): Generator;
/**
* The length of the arguments.
*/
readonly length: number;
/**
* Returns the name of the function.
*/
readonly name: string;
/**
* A reference to the prototype.
*/
readonly prototype: Generator;
}
interface GeneratorFunctionConstructor {
/**
* Creates a new Generator function.
* @param args A list of arguments the function accepts.
*/
new (...args: string[]): GeneratorFunction;
/**
* Creates a new Generator function.
* @param args A list of arguments the function accepts.
*/
(...args: string[]): GeneratorFunction;
/**
* The length of the arguments.
*/
readonly length: number;
/**
* Returns the name of the function.
*/
readonly name: string;
/**
* A reference to the prototype.
*/
readonly prototype: GeneratorFunction;
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"signatureFlags.js","sourceRoot":"","sources":["../../src/enums/signatureFlags.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,MAAM,CAAC,IAAI,cAAmB,CAAC;AAC/B,CAAC,UAAU,cAAc;IACrB,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IACpD,cAAc,CAAC,cAAc,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,kBAAkB,CAAC;IAC5E,cAAc,CAAC,cAAc,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,GAAG,iBAAiB,CAAC;IAC1E,cAAc,CAAC,cAAc,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC;IAC9D,cAAc,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;IAC5D,cAAc,CAAC,cAAc,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,GAAG,kBAAkB,CAAC;IAC7E,cAAc,CAAC,cAAc,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,GAAG,kBAAkB,CAAC;IAC7E,cAAc,CAAC,cAAc,CAAC,4BAA4B,CAAC,GAAG,EAAE,CAAC,GAAG,4BAA4B,CAAC;IACjG,cAAc,CAAC,cAAc,CAAC,iBAAiB,CAAC,GAAG,GAAG,CAAC,GAAG,iBAAiB,CAAC;IAC5E,cAAc,CAAC,cAAc,CAAC,wCAAwC,CAAC,GAAG,GAAG,CAAC,GAAG,wCAAwC,CAAC;IAC1H,cAAc,CAAC,cAAc,CAAC,kBAAkB,CAAC,GAAG,GAAG,CAAC,GAAG,kBAAkB,CAAC;IAC9E,cAAc,CAAC,cAAc,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,GAAG,gBAAgB,CAAC;AAC7E,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1 @@
(function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,b.base64js=a()}})(function(){return function(){function b(d,e,g){function a(j,i){if(!e[j]){if(!d[j]){var f="function"==typeof require&&require;if(!i&&f)return f(j,!0);if(h)return h(j,!0);var c=new Error("Cannot find module '"+j+"'");throw c.code="MODULE_NOT_FOUND",c}var k=e[j]={exports:{}};d[j][0].call(k.exports,function(b){var c=d[j][1][b];return a(c||b)},k,k.exports,b,d,e,g)}return e[j].exports}for(var h="function"==typeof require&&require,c=0;c<g.length;c++)a(g[c]);return a}return b}()({"/":[function(a,b,c){'use strict';function d(a){var b=a.length;if(0<b%4)throw new Error("Invalid string. Length must be a multiple of 4");var c=a.indexOf("=");-1===c&&(c=b);var d=c===b?0:4-c%4;return[c,d]}function e(a,b,c){return 3*(b+c)/4-c}function f(a){var b,c,f=d(a),g=f[0],h=f[1],j=new m(e(a,g,h)),k=0,n=0<h?g-4:g;for(c=0;c<n;c+=4)b=l[a.charCodeAt(c)]<<18|l[a.charCodeAt(c+1)]<<12|l[a.charCodeAt(c+2)]<<6|l[a.charCodeAt(c+3)],j[k++]=255&b>>16,j[k++]=255&b>>8,j[k++]=255&b;return 2===h&&(b=l[a.charCodeAt(c)]<<2|l[a.charCodeAt(c+1)]>>4,j[k++]=255&b),1===h&&(b=l[a.charCodeAt(c)]<<10|l[a.charCodeAt(c+1)]<<4|l[a.charCodeAt(c+2)]>>2,j[k++]=255&b>>8,j[k++]=255&b),j}function g(a){return k[63&a>>18]+k[63&a>>12]+k[63&a>>6]+k[63&a]}function h(a,b,c){for(var d,e=[],f=b;f<c;f+=3)d=(16711680&a[f]<<16)+(65280&a[f+1]<<8)+(255&a[f+2]),e.push(g(d));return e.join("")}function j(a){for(var b,c=a.length,d=c%3,e=[],f=16383,g=0,j=c-d;g<j;g+=f)e.push(h(a,g,g+f>j?j:g+f));return 1===d?(b=a[c-1],e.push(k[b>>2]+k[63&b<<4]+"==")):2===d&&(b=(a[c-2]<<8)+a[c-1],e.push(k[b>>10]+k[63&b>>4]+k[63&b<<2]+"=")),e.join("")}c.byteLength=function(a){var b=d(a),c=b[0],e=b[1];return 3*(c+e)/4-e},c.toByteArray=f,c.fromByteArray=j;for(var k=[],l=[],m="undefined"==typeof Uint8Array?Array:Uint8Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,p=n.length;o<p;++o)k[o]=n[o],l[n.charCodeAt(o)]=o;l[45]=62,l[95]=63},{}]},{},[])("/")});

View File

@@ -0,0 +1,551 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { ZodError, ZodIssueCode } from "../ZodError.js";
import { ZodParsedType } from "../helpers/util.js";
test("error creation", () => {
const err1 = ZodError.create([]);
err1.addIssue({
code: ZodIssueCode.invalid_type,
expected: ZodParsedType.object,
received: ZodParsedType.string,
path: [],
message: "",
fatal: true,
});
err1.isEmpty;
const err2 = ZodError.create(err1.issues);
const err3 = new ZodError([]);
err3.addIssues(err1.issues);
err3.addIssue(err1.issues[0]);
err1.message;
err2.message;
err3.message;
});
const errorMap: z.ZodErrorMap = (error, ctx) => {
if (error.code === ZodIssueCode.invalid_type) {
if (error.expected === "string") {
return { message: "bad type!" };
}
}
if (error.code === ZodIssueCode.custom) {
return { message: `less-than-${error.params?.minimum}` };
}
return { message: ctx.defaultError };
};
test("type error with custom error map", () => {
try {
z.string().parse(234, { errorMap });
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues[0].code).toEqual(z.ZodIssueCode.invalid_type);
expect(zerr.issues[0].message).toEqual(`bad type!`);
}
});
test("refinement fail with params", () => {
try {
z.number()
.refine((val) => val >= 3, {
params: { minimum: 3 },
})
.parse(2, { errorMap });
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues[0].code).toEqual(z.ZodIssueCode.custom);
expect(zerr.issues[0].message).toEqual(`less-than-3`);
}
});
test("custom error with custom errormap", () => {
try {
z.string()
.refine((val) => val.length > 12, {
params: { minimum: 13 },
message: "override",
})
.parse("asdf", { errorMap });
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues[0].message).toEqual("override");
}
});
test("default error message", () => {
try {
z.number()
.refine((x) => x > 3)
.parse(2);
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("Invalid input");
}
});
test("override error in refine", () => {
try {
z.number()
.refine((x) => x > 3, "override")
.parse(2);
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("override");
}
});
test("override error in refinement", () => {
try {
z.number()
.refine((x) => x > 3, {
message: "override",
})
.parse(2);
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("override");
}
});
test("array minimum", () => {
try {
z.array(z.string()).min(3, "tooshort").parse(["asdf", "qwer"]);
} catch (err) {
const zerr: ZodError = err as any;
expect(zerr.issues[0].code).toEqual(ZodIssueCode.too_small);
expect(zerr.issues[0].message).toEqual("tooshort");
}
try {
z.array(z.string()).min(3).parse(["asdf", "qwer"]);
} catch (err) {
const zerr: ZodError = err as any;
expect(zerr.issues[0].code).toEqual(ZodIssueCode.too_small);
expect(zerr.issues[0].message).toEqual(`Array must contain at least 3 element(s)`);
}
});
// implement test for semi-smart union logic that checks for type error on either left or right
// test("union smart errors", () => {
// // expect.assertions(2);
// const p1 = z
// .union([z.string(), z.number().refine((x) => x > 0)])
// .safeParse(-3.2);
// if (p1.success === true) throw new Error();
// expect(p1.success).toBe(false);
// expect(p1.error.issues[0].code).toEqual(ZodIssueCode.custom);
// const p2 = z.union([z.string(), z.number()]).safeParse(false);
// // .catch(err => expect(err.issues[0].code).toEqual(ZodIssueCode.invalid_union));
// if (p2.success === true) throw new Error();
// expect(p2.success).toBe(false);
// expect(p2.error.issues[0].code).toEqual(ZodIssueCode.invalid_union);
// });
test("custom path in custom error map", () => {
const schema = z.object({
items: z.array(z.string()).refine((data) => data.length > 3, {
path: ["items-too-few"],
}),
});
const errorMap: z.ZodErrorMap = (error) => {
expect(error.path.length).toBe(2);
return { message: "doesnt matter" };
};
const result = schema.safeParse({ items: ["first"] }, { errorMap });
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].path).toEqual(["items", "items-too-few"]);
}
});
test("error metadata from value", () => {
const dynamicRefine = z.string().refine(
(val) => val === val.toUpperCase(),
(val) => ({ params: { val } })
);
const result = dynamicRefine.safeParse("asdf");
expect(result.success).toEqual(false);
if (!result.success) {
const sub = result.error.issues[0];
expect(result.error.issues[0].code).toEqual("custom");
if (sub.code === "custom") {
expect(sub.params!.val).toEqual("asdf");
}
}
});
// test("don't call refine after validation failed", () => {
// const asdf = z
// .union([
// z.number(),
// z.string().transform(z.number(), (val) => {
// return parseFloat(val);
// }),
// ])
// .refine((v) => v >= 1);
// expect(() => asdf.safeParse("foo")).not.toThrow();
// });
test("root level formatting", () => {
const schema = z.string().email();
const result = schema.safeParse("asdfsdf");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.format()._errors).toEqual(["Invalid email"]);
}
});
test("custom path", () => {
const schema = z
.object({
password: z.string(),
confirm: z.string(),
})
.refine((val) => val.confirm === val.password, { path: ["confirm"] });
const result = schema.safeParse({
password: "peanuts",
confirm: "qeanuts",
});
expect(result.success).toEqual(false);
if (!result.success) {
// nested errors
const error = result.error.format();
expect(error._errors).toEqual([]);
expect(error.password?._errors).toEqual(undefined);
expect(error.confirm?._errors).toEqual(["Invalid input"]);
}
});
test("custom path", () => {
const schema = z
.object({
password: z.string().min(6),
confirm: z.string().min(6),
})
.refine((val) => val.confirm === val.password);
const result = schema.safeParse({
password: "qwer",
confirm: "asdf",
});
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues.length).toEqual(3);
}
});
const schema = z.object({
inner: z.object({
name: z
.string()
.refine((val) => val.length > 5)
.array()
.refine((val) => val.length <= 1),
}),
});
test("no abort early on refinements", () => {
const invalidItem = {
inner: { name: ["aasd", "asdfasdfasfd"] },
};
const result1 = schema.safeParse(invalidItem);
expect(result1.success).toEqual(false);
if (!result1.success) {
expect(result1.error.issues.length).toEqual(2);
}
});
test("formatting", () => {
const invalidItem = {
inner: { name: ["aasd", "asdfasdfasfd"] },
};
const invalidArray = {
inner: { name: ["asdfasdf", "asdfasdfasfd"] },
};
const result1 = schema.safeParse(invalidItem);
const result2 = schema.safeParse(invalidArray);
expect(result1.success).toEqual(false);
expect(result2.success).toEqual(false);
if (!result1.success) {
const error = result1.error.format();
expect(error._errors).toEqual([]);
expect(error.inner?._errors).toEqual([]);
// expect(error.inner?.name?._errors).toEqual(["Invalid input"]);
// expect(error.inner?.name?.[0]._errors).toEqual(["Invalid input"]);
expect(error.inner?.name?.[1]).toEqual(undefined);
}
if (!result2.success) {
type FormattedError = z.inferFormattedError<typeof schema>;
const error: FormattedError = result2.error.format();
expect(error._errors).toEqual([]);
expect(error.inner?._errors).toEqual([]);
expect(error.inner?.name?._errors).toEqual(["Invalid input"]);
expect(error.inner?.name?.[0]).toEqual(undefined);
expect(error.inner?.name?.[1]).toEqual(undefined);
expect(error.inner?.name?.[2]).toEqual(undefined);
}
// test custom mapper
if (!result2.success) {
type FormattedError = z.inferFormattedError<typeof schema, number>;
const error: FormattedError = result2.error.format(() => 5);
expect(error._errors).toEqual([]);
expect(error.inner?._errors).toEqual([]);
expect(error.inner?.name?._errors).toEqual([5]);
}
});
test("formatting with nullable and optional fields", () => {
const nameSchema = z.string().refine((val) => val.length > 5);
const schema = z.object({
nullableObject: z.object({ name: nameSchema }).nullable(),
nullableArray: z.array(nameSchema).nullable(),
nullableTuple: z.tuple([nameSchema, nameSchema, z.number()]).nullable(),
optionalObject: z.object({ name: nameSchema }).optional(),
optionalArray: z.array(nameSchema).optional(),
optionalTuple: z.tuple([nameSchema, nameSchema, z.number()]).optional(),
});
const invalidItem = {
nullableObject: { name: "abcd" },
nullableArray: ["abcd"],
nullableTuple: ["abcd", "abcd", 1],
optionalObject: { name: "abcd" },
optionalArray: ["abcd"],
optionalTuple: ["abcd", "abcd", 1],
};
const result = schema.safeParse(invalidItem);
expect(result.success).toEqual(false);
if (!result.success) {
type FormattedError = z.inferFormattedError<typeof schema>;
const error: FormattedError = result.error.format();
expect(error._errors).toEqual([]);
expect(error.nullableObject?._errors).toEqual([]);
expect(error.nullableObject?.name?._errors).toEqual(["Invalid input"]);
expect(error.nullableArray?._errors).toEqual([]);
expect(error.nullableArray?.[0]?._errors).toEqual(["Invalid input"]);
expect(error.nullableTuple?._errors).toEqual([]);
expect(error.nullableTuple?.[0]?._errors).toEqual(["Invalid input"]);
expect(error.nullableTuple?.[1]?._errors).toEqual(["Invalid input"]);
expect(error.optionalObject?._errors).toEqual([]);
expect(error.optionalObject?.name?._errors).toEqual(["Invalid input"]);
expect(error.optionalArray?._errors).toEqual([]);
expect(error.optionalArray?.[0]?._errors).toEqual(["Invalid input"]);
expect(error.optionalTuple?._errors).toEqual([]);
expect(error.optionalTuple?.[0]?._errors).toEqual(["Invalid input"]);
expect(error.optionalTuple?.[1]?._errors).toEqual(["Invalid input"]);
}
});
const stringWithCustomError = z.string({
errorMap: (issue, ctx) => ({
message: issue.code === "invalid_type" ? (ctx.data ? "Invalid name" : "Name is required") : ctx.defaultError,
}),
});
test("schema-bound error map", () => {
const result = stringWithCustomError.safeParse(1234);
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("Invalid name");
}
const result2 = stringWithCustomError.safeParse(undefined);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].message).toEqual("Name is required");
}
// support contextual override
const result3 = stringWithCustomError.safeParse(undefined, {
errorMap: () => ({ message: "OVERRIDE" }),
});
expect(result3.success).toEqual(false);
if (!result3.success) {
expect(result3.error.issues[0].message).toEqual("OVERRIDE");
}
});
test("overrideErrorMap", () => {
// support overrideErrorMap
z.setErrorMap(() => ({ message: "OVERRIDE" }));
const result4 = stringWithCustomError.min(10).safeParse("tooshort");
expect(result4.success).toEqual(false);
if (!result4.success) {
expect(result4.error.issues[0].message).toEqual("OVERRIDE");
}
z.setErrorMap(z.defaultErrorMap);
});
test("invalid and required", () => {
const str = z.string({
invalid_type_error: "Invalid name",
required_error: "Name is required",
});
const result1 = str.safeParse(1234);
expect(result1.success).toEqual(false);
if (!result1.success) {
expect(result1.error.issues[0].message).toEqual("Invalid name");
}
const result2 = str.safeParse(undefined);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].message).toEqual("Name is required");
}
});
test("Fallback to default required error", () => {
const str = z.string({
invalid_type_error: "Invalid name",
// required_error: "Name is required",
});
const result2 = str.safeParse(undefined);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].message).toEqual("Required");
}
});
test("invalid and required and errorMap", () => {
expect(() => {
return z.string({
invalid_type_error: "Invalid name",
required_error: "Name is required",
errorMap: () => ({ message: "OVERRIDE" }),
});
}).toThrow();
});
test("strict error message", () => {
const errorMsg = "Invalid object";
const obj = z.object({ x: z.string() }).strict(errorMsg);
const result = obj.safeParse({ x: "a", y: "b" });
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual(errorMsg);
}
});
test("enum error message, invalid enum elementstring", () => {
try {
z.enum(["Tuna", "Trout"]).parse("Salmon");
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("Invalid enum value. Expected 'Tuna' | 'Trout', received 'Salmon'");
}
});
test("enum error message, invalid type", () => {
try {
z.enum(["Tuna", "Trout"]).parse(12);
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("Expected 'Tuna' | 'Trout', received number");
}
});
test("nativeEnum default error message", () => {
enum Fish {
Tuna = "Tuna",
Trout = "Trout",
}
try {
z.nativeEnum(Fish).parse("Salmon");
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("Invalid enum value. Expected 'Tuna' | 'Trout', received 'Salmon'");
}
});
test("literal default error message", () => {
try {
z.literal("Tuna").parse("Trout");
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual(`Invalid literal value, expected "Tuna"`);
}
});
test("literal bigint default error message", () => {
try {
z.literal(BigInt(12)).parse(BigInt(13));
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual(`Invalid literal value, expected "12"`);
}
});
test("enum with message returns the custom error message", () => {
const schema = z.enum(["apple", "banana"], {
message: "the value provided is invalid",
});
const result1 = schema.safeParse("berries");
expect(result1.success).toEqual(false);
if (!result1.success) {
expect(result1.error.issues[0].message).toEqual("the value provided is invalid");
}
const result2 = schema.safeParse(undefined);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].message).toEqual("the value provided is invalid");
}
const result3 = schema.safeParse("banana");
expect(result3.success).toEqual(true);
const result4 = schema.safeParse(null);
expect(result4.success).toEqual(false);
if (!result4.success) {
expect(result4.error.issues[0].message).toEqual("the value provided is invalid");
}
});
test("when the message is falsy, it is used as is provided", () => {
const schema = z.string().max(1, { message: "" });
const result = schema.safeParse("asdf");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("");
}
});
// test("dont short circuit on continuable errors", () => {
// const user = z
// .object({
// password: z.string().min(6),
// confirm: z.string(),
// })
// .refine((data) => data.password === data.confirm, {
// message: "Passwords don't match",
// path: ["confirm"],
// });
// const result = user.safeParse({ password: "asdf", confirm: "qwer" });
// if (!result.success) {
// expect(result.error.issues.length).toEqual(2);
// }
// });

View File

@@ -0,0 +1,6 @@
import { _ as _array_like_to_array } from "./_array_like_to_array.js";
function _array_without_holes(arr) {
if (Array.isArray(arr)) return _array_like_to_array(arr);
}
export { _array_without_holes as _ };

View File

@@ -0,0 +1,36 @@
"use strict";
/* eslint-disable @typescript-eslint/no-namespace */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LegacyESLint = void 0;
const eslint_1 = require("eslint");
const use_at_your_own_risk_1 = __importDefault(require("eslint/use-at-your-own-risk"));
function throwMissingLegacyESLintError() {
throw new Error('LegacyESLint is not available with the current version of ESLint.');
}
/* eslint-disable-next-line @typescript-eslint/no-extraneous-class */
class MissingLegacyESLint {
static configType = 'eslintrc';
static version = eslint_1.ESLint.version;
constructor() {
throwMissingLegacyESLintError();
}
static getErrorResults() {
throwMissingLegacyESLintError();
}
static outputFixes() {
throwMissingLegacyESLintError();
}
}
/**
* The ESLint class is the primary class to use in Node.js applications.
* This class depends on the Node.js fs module and the file system, so you cannot use it in browsers.
*
* If you want to lint code on browsers, use the Linter class instead.
*/
class LegacyESLint extends (use_at_your_own_risk_1.default.LegacyESLint ??
MissingLegacyESLint) {
}
exports.LegacyESLint = LegacyESLint;