WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getThisExpression = getThisExpression;
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
function getThisExpression(node) {
|
||||
while (true) {
|
||||
if (node.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
||||
node = node.callee;
|
||||
}
|
||||
else if (node.type === utils_1.AST_NODE_TYPES.ThisExpression) {
|
||||
return node;
|
||||
}
|
||||
else if (node.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
||||
node = node.object;
|
||||
}
|
||||
else if (node.type === utils_1.AST_NODE_TYPES.ChainExpression) {
|
||||
node = node.expression;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "តួអក្សរ", verb: "គួរមាន" },
|
||||
file: { unit: "បៃ", verb: "គួរមាន" },
|
||||
array: { unit: "ធាតុ", verb: "គួរមាន" },
|
||||
set: { unit: "ធាតុ", verb: "គួរមាន" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const FormatDictionary: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "ទិន្នន័យបញ្ចូល",
|
||||
email: "អាសយដ្ឋានអ៊ីមែល",
|
||||
url: "URL",
|
||||
emoji: "សញ្ញាអារម្មណ៍",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "កាលបរិច្ឆេទ និងម៉ោង ISO",
|
||||
date: "កាលបរិច្ឆេទ ISO",
|
||||
time: "ម៉ោង ISO",
|
||||
duration: "រយៈពេល ISO",
|
||||
ipv4: "អាសយដ្ឋាន IPv4",
|
||||
ipv6: "អាសយដ្ឋាន IPv6",
|
||||
cidrv4: "ដែនអាសយដ្ឋាន IPv4",
|
||||
cidrv6: "ដែនអាសយដ្ឋាន IPv6",
|
||||
base64: "ខ្សែអក្សរអ៊ិកូដ base64",
|
||||
base64url: "ខ្សែអក្សរអ៊ិកូដ base64url",
|
||||
json_string: "ខ្សែអក្សរ JSON",
|
||||
e164: "លេខ E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "ទិន្នន័យបញ្ចូល",
|
||||
};
|
||||
|
||||
const TypeDictionary: {
|
||||
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
|
||||
} = {
|
||||
nan: "NaN",
|
||||
number: "លេខ",
|
||||
array: "អារេ (Array)",
|
||||
null: "គ្មានតម្លៃ (null)",
|
||||
};
|
||||
|
||||
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 `ទិន្នន័យបញ្ចូលមិនត្រឹមត្រូវ៖ ត្រូវការ instanceof ${issue.expected} ប៉ុន្តែទទួលបាន ${received}`;
|
||||
}
|
||||
return `ទិន្នន័យបញ្ចូលមិនត្រឹមត្រូវ៖ ត្រូវការ ${expected} ប៉ុន្តែទទួលបាន ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1) return `ទិន្នន័យបញ្ចូលមិនត្រឹមត្រូវ៖ ត្រូវការ ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `ជម្រើសមិនត្រឹមត្រូវ៖ ត្រូវជាមួយក្នុងចំណោម ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `ធំពេក៖ ត្រូវការ ${issue.origin ?? "តម្លៃ"} ${adj} ${issue.maximum.toString()} ${sizing.unit ?? "ធាតុ"}`;
|
||||
return `ធំពេក៖ ត្រូវការ ${issue.origin ?? "តម្លៃ"} ${adj} ${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `តូចពេក៖ ត្រូវការ ${issue.origin} ${adj} ${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `តូចពេក៖ ត្រូវការ ${issue.origin} ${adj} ${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") {
|
||||
return `ខ្សែអក្សរមិនត្រឹមត្រូវ៖ ត្រូវចាប់ផ្តើមដោយ "${_issue.prefix}"`;
|
||||
}
|
||||
if (_issue.format === "ends_with") return `ខ្សែអក្សរមិនត្រឹមត្រូវ៖ ត្រូវបញ្ចប់ដោយ "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `ខ្សែអក្សរមិនត្រឹមត្រូវ៖ ត្រូវមាន "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `ខ្សែអក្សរមិនត្រឹមត្រូវ៖ ត្រូវតែផ្គូផ្គងនឹងទម្រង់ដែលបានកំណត់ ${_issue.pattern}`;
|
||||
return `មិនត្រឹមត្រូវ៖ ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `លេខមិនត្រឹមត្រូវ៖ ត្រូវតែជាពហុគុណនៃ ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `រកឃើញសោមិនស្គាល់៖ ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `សោមិនត្រឹមត្រូវនៅក្នុង ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return `ទិន្នន័យមិនត្រឹមត្រូវ`;
|
||||
case "invalid_element":
|
||||
return `ទិន្នន័យមិនត្រឹមត្រូវនៅក្នុង ${issue.origin}`;
|
||||
default:
|
||||
return `ទិន្នន័យមិនត្រឹមត្រូវ`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Arnout Kazemier
|
||||
|
||||
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,3 @@
|
||||
declare function findMockRedirect(root: string, mockPath: string, external: string | null): string | null;
|
||||
|
||||
export { findMockRedirect };
|
||||
@@ -0,0 +1,970 @@
|
||||
declare module "node:net" {
|
||||
import { NonSharedBuffer } from "node:buffer";
|
||||
import * as dns from "node:dns";
|
||||
import { Abortable, EventEmitter, InternalEventEmitter } from "node:events";
|
||||
import * as stream from "node:stream";
|
||||
type LookupFunction = (
|
||||
hostname: string,
|
||||
options: dns.LookupOptions,
|
||||
callback: (err: NodeJS.ErrnoException | null, address: string | dns.LookupAddress[], family?: number) => void,
|
||||
) => void;
|
||||
interface AddressInfo {
|
||||
address: string;
|
||||
family: string;
|
||||
port: number;
|
||||
}
|
||||
interface SocketConstructorOpts {
|
||||
fd?: number | undefined;
|
||||
allowHalfOpen?: boolean | undefined;
|
||||
onread?: OnReadOpts | undefined;
|
||||
readable?: boolean | undefined;
|
||||
writable?: boolean | undefined;
|
||||
signal?: AbortSignal | undefined;
|
||||
noDelay?: boolean | undefined;
|
||||
keepAlive?: boolean | undefined;
|
||||
keepAliveInitialDelay?: number | undefined;
|
||||
blockList?: BlockList | undefined;
|
||||
typeOfService?: number | undefined;
|
||||
}
|
||||
interface OnReadOpts {
|
||||
buffer: Uint8Array | (() => Uint8Array);
|
||||
/**
|
||||
* This function is called for every chunk of incoming data.
|
||||
* Two arguments are passed to it: the number of bytes written to `buffer` and a reference to `buffer`.
|
||||
* Return `false` from this function to implicitly `pause()` the socket.
|
||||
*/
|
||||
callback(bytesWritten: number, buffer: Uint8Array): boolean;
|
||||
}
|
||||
interface TcpSocketConnectOpts {
|
||||
port: number;
|
||||
host?: string | undefined;
|
||||
localAddress?: string | undefined;
|
||||
localPort?: number | undefined;
|
||||
hints?: number | undefined;
|
||||
family?: number | undefined;
|
||||
lookup?: LookupFunction | undefined;
|
||||
/**
|
||||
* @since v18.13.0
|
||||
*/
|
||||
autoSelectFamily?: boolean | undefined;
|
||||
/**
|
||||
* @since v18.13.0
|
||||
*/
|
||||
autoSelectFamilyAttemptTimeout?: number | undefined;
|
||||
}
|
||||
interface IpcSocketConnectOpts {
|
||||
path: string;
|
||||
}
|
||||
type SocketConnectOpts = TcpSocketConnectOpts | IpcSocketConnectOpts;
|
||||
type SocketReadyState = "opening" | "open" | "readOnly" | "writeOnly" | "closed";
|
||||
interface SocketEventMap extends Omit<stream.DuplexEventMap, "close"> {
|
||||
"close": [hadError: boolean];
|
||||
"connect": [];
|
||||
"connectionAttempt": [ip: string, port: number, family: number];
|
||||
"connectionAttemptFailed": [ip: string, port: number, family: number, error: Error];
|
||||
"connectionAttemptTimeout": [ip: string, port: number, family: number];
|
||||
"data": [data: string | NonSharedBuffer];
|
||||
"lookup": [err: Error | null, address: string, family: number | null, host: string];
|
||||
"ready": [];
|
||||
"timeout": [];
|
||||
}
|
||||
/**
|
||||
* This class is an abstraction of a TCP socket or a streaming `IPC` endpoint
|
||||
* (uses named pipes on Windows, and Unix domain sockets otherwise). It is also
|
||||
* an `EventEmitter`.
|
||||
*
|
||||
* A `net.Socket` can be created by the user and used directly to interact with
|
||||
* a server. For example, it is returned by {@link createConnection},
|
||||
* so the user can use it to talk to the server.
|
||||
*
|
||||
* It can also be created by Node.js and passed to the user when a connection
|
||||
* is received. For example, it is passed to the listeners of a `'connection'` event emitted on a {@link Server}, so the user can use
|
||||
* it to interact with the client.
|
||||
* @since v0.3.4
|
||||
*/
|
||||
class Socket extends stream.Duplex {
|
||||
constructor(options?: SocketConstructorOpts);
|
||||
/**
|
||||
* Destroys the socket after all data is written. If the `finish` event was already emitted the socket is destroyed immediately.
|
||||
* If the socket is still writable it implicitly calls `socket.end()`.
|
||||
* @since v0.3.4
|
||||
*/
|
||||
destroySoon(): void;
|
||||
/**
|
||||
* Sends data on the socket. The second parameter specifies the encoding in the
|
||||
* case of a string. It defaults to UTF8 encoding.
|
||||
*
|
||||
* Returns `true` if the entire data was flushed successfully to the kernel
|
||||
* buffer. Returns `false` if all or part of the data was queued in user memory.`'drain'` will be emitted when the buffer is again free.
|
||||
*
|
||||
* The optional `callback` parameter will be executed when the data is finally
|
||||
* written out, which may not be immediately.
|
||||
*
|
||||
* See `Writable` stream `write()` method for more
|
||||
* information.
|
||||
* @since v0.1.90
|
||||
*/
|
||||
write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean;
|
||||
/**
|
||||
* Sends data on the socket, with an explicit encoding for string data.
|
||||
* @see {@link Socket.write} for full details.
|
||||
* @since v0.1.90
|
||||
* @param [encoding='utf8'] Only used when data is `string`.
|
||||
*/
|
||||
write(str: Uint8Array | string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean;
|
||||
/**
|
||||
* Initiate a connection on a given socket.
|
||||
*
|
||||
* Possible signatures:
|
||||
*
|
||||
* * `socket.connect(options[, connectListener])`
|
||||
* * `socket.connect(path[, connectListener])` for `IPC` connections.
|
||||
* * `socket.connect(port[, host][, connectListener])` for TCP connections.
|
||||
* * Returns: `net.Socket` The socket itself.
|
||||
*
|
||||
* This function is asynchronous. When the connection is established, the `'connect'` event will be emitted. If there is a problem connecting,
|
||||
* instead of a `'connect'` event, an `'error'` event will be emitted with
|
||||
* the error passed to the `'error'` listener.
|
||||
* The last parameter `connectListener`, if supplied, will be added as a listener
|
||||
* for the `'connect'` event **once**.
|
||||
*
|
||||
* This function should only be used for reconnecting a socket after`'close'` has been emitted or otherwise it may lead to undefined
|
||||
* behavior.
|
||||
*/
|
||||
connect(options: SocketConnectOpts, connectionListener?: () => void): this;
|
||||
connect(port: number, host: string, connectionListener?: () => void): this;
|
||||
connect(port: number, connectionListener?: () => void): this;
|
||||
connect(path: string, connectionListener?: () => void): this;
|
||||
/**
|
||||
* Set the encoding for the socket as a `Readable Stream`. See `readable.setEncoding()` for more information.
|
||||
* @since v0.1.90
|
||||
* @return The socket itself.
|
||||
*/
|
||||
setEncoding(encoding?: BufferEncoding): this;
|
||||
/**
|
||||
* Pauses the reading of data. That is, `'data'` events will not be emitted.
|
||||
* Useful to throttle back an upload.
|
||||
* @return The socket itself.
|
||||
*/
|
||||
pause(): this;
|
||||
/**
|
||||
* Close the TCP connection by sending an RST packet and destroy the stream.
|
||||
* If this TCP socket is in connecting status, it will send an RST packet and destroy this TCP socket once it is connected.
|
||||
* Otherwise, it will call `socket.destroy` with an `ERR_SOCKET_CLOSED` Error.
|
||||
* If this is not a TCP socket (for example, a pipe), calling this method will immediately throw an `ERR_INVALID_HANDLE_TYPE` Error.
|
||||
* @since v18.3.0, v16.17.0
|
||||
*/
|
||||
resetAndDestroy(): this;
|
||||
/**
|
||||
* Resumes reading after a call to `socket.pause()`.
|
||||
* @return The socket itself.
|
||||
*/
|
||||
resume(): this;
|
||||
/**
|
||||
* Sets the socket to timeout after `timeout` milliseconds of inactivity on
|
||||
* the socket. By default `net.Socket` do not have a timeout.
|
||||
*
|
||||
* When an idle timeout is triggered the socket will receive a `'timeout'` event but the connection will not be severed. The user must manually call `socket.end()` or `socket.destroy()` to
|
||||
* end the connection.
|
||||
*
|
||||
* ```js
|
||||
* socket.setTimeout(3000);
|
||||
* socket.on('timeout', () => {
|
||||
* console.log('socket timeout');
|
||||
* socket.end();
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* If `timeout` is 0, then the existing idle timeout is disabled.
|
||||
*
|
||||
* The optional `callback` parameter will be added as a one-time listener for the `'timeout'` event.
|
||||
* @since v0.1.90
|
||||
* @return The socket itself.
|
||||
*/
|
||||
setTimeout(timeout: number, callback?: () => void): this;
|
||||
/**
|
||||
* Enable/disable the use of Nagle's algorithm.
|
||||
*
|
||||
* When a TCP connection is created, it will have Nagle's algorithm enabled.
|
||||
*
|
||||
* Nagle's algorithm delays data before it is sent via the network. It attempts
|
||||
* to optimize throughput at the expense of latency.
|
||||
*
|
||||
* Passing `true` for `noDelay` or not passing an argument will disable Nagle's
|
||||
* algorithm for the socket. Passing `false` for `noDelay` will enable Nagle's
|
||||
* algorithm.
|
||||
* @since v0.1.90
|
||||
* @param [noDelay=true]
|
||||
* @return The socket itself.
|
||||
*/
|
||||
setNoDelay(noDelay?: boolean): this;
|
||||
/**
|
||||
* Enable/disable keep-alive functionality, and optionally set the initial
|
||||
* delay before the first keepalive probe is sent on an idle socket.
|
||||
*
|
||||
* Set `initialDelay` (in milliseconds) to set the delay between the last
|
||||
* data packet received and the first keepalive probe. Setting `0` for`initialDelay` will leave the value unchanged from the default
|
||||
* (or previous) setting.
|
||||
*
|
||||
* Enabling the keep-alive functionality will set the following socket options:
|
||||
*
|
||||
* * `SO_KEEPALIVE=1`
|
||||
* * `TCP_KEEPIDLE=initialDelay`
|
||||
* * `TCP_KEEPCNT=10`
|
||||
* * `TCP_KEEPINTVL=1`
|
||||
* @since v0.1.92
|
||||
* @param [enable=false]
|
||||
* @param [initialDelay=0]
|
||||
* @return The socket itself.
|
||||
*/
|
||||
setKeepAlive(enable?: boolean, initialDelay?: number): this;
|
||||
/**
|
||||
* Returns the current Type of Service (TOS) field for IPv4 packets or Traffic
|
||||
* Class for IPv6 packets for this socket.
|
||||
*
|
||||
* `setTypeOfService()` may be called before the socket is connected; the value
|
||||
* will be cached and applied when the socket establishes a connection.
|
||||
* `getTypeOfService()` will return the currently set value even before connection.
|
||||
*
|
||||
* On some platforms (e.g., Linux), certain TOS/ECN bits may be masked or ignored,
|
||||
* and behavior can differ between IPv4 and IPv6 or dual-stack sockets. Callers
|
||||
* should verify platform-specific semantics.
|
||||
* @since v25.6.0
|
||||
* @returns The current TOS value.
|
||||
*/
|
||||
getTypeOfService(): number;
|
||||
/**
|
||||
* Sets the Type of Service (TOS) field for IPv4 packets or Traffic Class for IPv6
|
||||
* Packets sent from this socket. This can be used to prioritize network traffic.
|
||||
*
|
||||
* `setTypeOfService()` may be called before the socket is connected; the value
|
||||
* will be cached and applied when the socket establishes a connection.
|
||||
* `getTypeOfService()` will return the currently set value even before connection.
|
||||
*
|
||||
* On some platforms (e.g., Linux), certain TOS/ECN bits may be masked or ignored,
|
||||
* and behavior can differ between IPv4 and IPv6 or dual-stack sockets. Callers
|
||||
* should verify platform-specific semantics.
|
||||
* @since v25.6.0
|
||||
* @param tos The TOS value to set (0-255).
|
||||
* @returns The socket itself.
|
||||
*/
|
||||
setTypeOfService(tos: number): this;
|
||||
/**
|
||||
* Returns the bound `address`, the address `family` name and `port` of the
|
||||
* socket as reported by the operating system:`{ port: 12346, family: 'IPv4', address: '127.0.0.1' }`
|
||||
* @since v0.1.90
|
||||
*/
|
||||
address(): AddressInfo | {};
|
||||
/**
|
||||
* Calling `unref()` on a socket will allow the program to exit if this is the only
|
||||
* active socket in the event system. If the socket is already `unref`ed calling`unref()` again will have no effect.
|
||||
* @since v0.9.1
|
||||
* @return The socket itself.
|
||||
*/
|
||||
unref(): this;
|
||||
/**
|
||||
* Opposite of `unref()`, calling `ref()` on a previously `unref`ed socket will _not_ let the program exit if it's the only socket left (the default behavior).
|
||||
* If the socket is `ref`ed calling `ref` again will have no effect.
|
||||
* @since v0.9.1
|
||||
* @return The socket itself.
|
||||
*/
|
||||
ref(): this;
|
||||
/**
|
||||
* This property is only present if the family autoselection algorithm is enabled in `socket.connect(options)`
|
||||
* and it is an array of the addresses that have been attempted.
|
||||
*
|
||||
* Each address is a string in the form of `$IP:$PORT`.
|
||||
* If the connection was successful, then the last address is the one that the socket is currently connected to.
|
||||
* @since v19.4.0
|
||||
*/
|
||||
readonly autoSelectFamilyAttemptedAddresses: string[];
|
||||
/**
|
||||
* This property shows the number of characters buffered for writing. The buffer
|
||||
* may contain strings whose length after encoding is not yet known. So this number
|
||||
* is only an approximation of the number of bytes in the buffer.
|
||||
*
|
||||
* `net.Socket` has the property that `socket.write()` always works. This is to
|
||||
* help users get up and running quickly. The computer cannot always keep up
|
||||
* with the amount of data that is written to a socket. The network connection
|
||||
* simply might be too slow. Node.js will internally queue up the data written to a
|
||||
* socket and send it out over the wire when it is possible.
|
||||
*
|
||||
* The consequence of this internal buffering is that memory may grow.
|
||||
* Users who experience large or growing `bufferSize` should attempt to
|
||||
* "throttle" the data flows in their program with `socket.pause()` and `socket.resume()`.
|
||||
* @since v0.3.8
|
||||
* @deprecated Since v14.6.0 - Use `writableLength` instead.
|
||||
*/
|
||||
readonly bufferSize: number;
|
||||
/**
|
||||
* The amount of received bytes.
|
||||
* @since v0.5.3
|
||||
*/
|
||||
readonly bytesRead: number;
|
||||
/**
|
||||
* The amount of bytes sent.
|
||||
* @since v0.5.3
|
||||
*/
|
||||
readonly bytesWritten: number;
|
||||
/**
|
||||
* If `true`, `socket.connect(options[, connectListener])` was
|
||||
* called and has not yet finished. It will stay `true` until the socket becomes
|
||||
* connected, then it is set to `false` and the `'connect'` event is emitted. Note
|
||||
* that the `socket.connect(options[, connectListener])` callback is a listener for the `'connect'` event.
|
||||
* @since v6.1.0
|
||||
*/
|
||||
readonly connecting: boolean;
|
||||
/**
|
||||
* This is `true` if the socket is not connected yet, either because `.connect()`has not yet been called or because it is still in the process of connecting
|
||||
* (see `socket.connecting`).
|
||||
* @since v11.2.0, v10.16.0
|
||||
*/
|
||||
readonly pending: boolean;
|
||||
/**
|
||||
* See `writable.destroyed` for further details.
|
||||
*/
|
||||
readonly destroyed: boolean;
|
||||
/**
|
||||
* The string representation of the local IP address the remote client is
|
||||
* connecting on. For example, in a server listening on `'0.0.0.0'`, if a client
|
||||
* connects on `'192.168.1.1'`, the value of `socket.localAddress` would be`'192.168.1.1'`.
|
||||
* @since v0.9.6
|
||||
*/
|
||||
readonly localAddress?: string;
|
||||
/**
|
||||
* The numeric representation of the local port. For example, `80` or `21`.
|
||||
* @since v0.9.6
|
||||
*/
|
||||
readonly localPort?: number;
|
||||
/**
|
||||
* The string representation of the local IP family. `'IPv4'` or `'IPv6'`.
|
||||
* @since v18.8.0, v16.18.0
|
||||
*/
|
||||
readonly localFamily?: string;
|
||||
/**
|
||||
* This property represents the state of the connection as a string.
|
||||
*
|
||||
* * If the stream is connecting `socket.readyState` is `opening`.
|
||||
* * If the stream is readable and writable, it is `open`.
|
||||
* * If the stream is readable and not writable, it is `readOnly`.
|
||||
* * If the stream is not readable and writable, it is `writeOnly`.
|
||||
* @since v0.5.0
|
||||
*/
|
||||
readonly readyState: SocketReadyState;
|
||||
/**
|
||||
* The string representation of the remote IP address. For example,`'74.125.127.100'` or `'2001:4860:a005::68'`. Value may be `undefined` if
|
||||
* the socket is destroyed (for example, if the client disconnected).
|
||||
* @since v0.5.10
|
||||
*/
|
||||
readonly remoteAddress: string | undefined;
|
||||
/**
|
||||
* The string representation of the remote IP family. `'IPv4'` or `'IPv6'`. Value may be `undefined` if
|
||||
* the socket is destroyed (for example, if the client disconnected).
|
||||
* @since v0.11.14
|
||||
*/
|
||||
readonly remoteFamily: string | undefined;
|
||||
/**
|
||||
* The numeric representation of the remote port. For example, `80` or `21`. Value may be `undefined` if
|
||||
* the socket is destroyed (for example, if the client disconnected).
|
||||
* @since v0.5.10
|
||||
*/
|
||||
readonly remotePort: number | undefined;
|
||||
/**
|
||||
* The socket timeout in milliseconds as set by `socket.setTimeout()`.
|
||||
* It is `undefined` if a timeout has not been set.
|
||||
* @since v10.7.0
|
||||
*/
|
||||
readonly timeout?: number;
|
||||
/**
|
||||
* Half-closes the socket. i.e., it sends a FIN packet. It is possible the
|
||||
* server will still send some data.
|
||||
*
|
||||
* See `writable.end()` for further details.
|
||||
* @since v0.1.90
|
||||
* @param callback Optional callback for when the socket is finished.
|
||||
* @return The socket itself.
|
||||
*/
|
||||
end(callback?: () => void): this;
|
||||
/**
|
||||
* Half-closes the socket, with one final chunk of data.
|
||||
* @see {@link Socket.end} for full details.
|
||||
* @since v0.1.90
|
||||
* @param callback Optional callback for when the socket is finished.
|
||||
* @return The socket itself.
|
||||
*/
|
||||
end(buffer: Uint8Array | string, callback?: () => void): this;
|
||||
/**
|
||||
* Half-closes the socket, with one final chunk of data.
|
||||
* @see {@link Socket.end} for full details.
|
||||
* @since v0.1.90
|
||||
* @param [encoding='utf8'] Only used when data is `string`.
|
||||
* @param callback Optional callback for when the socket is finished.
|
||||
* @return The socket itself.
|
||||
*/
|
||||
end(str: Uint8Array | string, encoding?: BufferEncoding, callback?: () => void): this;
|
||||
// #region InternalEventEmitter
|
||||
addListener<E extends keyof SocketEventMap>(eventName: E, listener: (...args: SocketEventMap[E]) => void): this;
|
||||
addListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
|
||||
emit<E extends keyof SocketEventMap>(eventName: E, ...args: SocketEventMap[E]): boolean;
|
||||
emit(eventName: string | symbol, ...args: any[]): boolean;
|
||||
listenerCount<E extends keyof SocketEventMap>(
|
||||
eventName: E,
|
||||
listener?: (...args: SocketEventMap[E]) => void,
|
||||
): number;
|
||||
listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number;
|
||||
listeners<E extends keyof SocketEventMap>(eventName: E): ((...args: SocketEventMap[E]) => void)[];
|
||||
listeners(eventName: string | symbol): ((...args: any[]) => void)[];
|
||||
off<E extends keyof SocketEventMap>(eventName: E, listener: (...args: SocketEventMap[E]) => void): this;
|
||||
off(eventName: string | symbol, listener: (...args: any[]) => void): this;
|
||||
on<E extends keyof SocketEventMap>(eventName: E, listener: (...args: SocketEventMap[E]) => void): this;
|
||||
on(eventName: string | symbol, listener: (...args: any[]) => void): this;
|
||||
once<E extends keyof SocketEventMap>(eventName: E, listener: (...args: SocketEventMap[E]) => void): this;
|
||||
once(eventName: string | symbol, listener: (...args: any[]) => void): this;
|
||||
prependListener<E extends keyof SocketEventMap>(
|
||||
eventName: E,
|
||||
listener: (...args: SocketEventMap[E]) => void,
|
||||
): this;
|
||||
prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
|
||||
prependOnceListener<E extends keyof SocketEventMap>(
|
||||
eventName: E,
|
||||
listener: (...args: SocketEventMap[E]) => void,
|
||||
): this;
|
||||
prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
|
||||
rawListeners<E extends keyof SocketEventMap>(eventName: E): ((...args: SocketEventMap[E]) => void)[];
|
||||
rawListeners(eventName: string | symbol): ((...args: any[]) => void)[];
|
||||
// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
|
||||
removeAllListeners<E extends keyof SocketEventMap>(eventName?: E): this;
|
||||
removeAllListeners(eventName?: string | symbol): this;
|
||||
removeListener<E extends keyof SocketEventMap>(
|
||||
eventName: E,
|
||||
listener: (...args: SocketEventMap[E]) => void,
|
||||
): this;
|
||||
removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
|
||||
// #endregion
|
||||
}
|
||||
interface ListenOptions extends Abortable {
|
||||
backlog?: number | undefined;
|
||||
exclusive?: boolean | undefined;
|
||||
host?: string | undefined;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ipv6Only?: boolean | undefined;
|
||||
reusePort?: boolean | undefined;
|
||||
path?: string | undefined;
|
||||
port?: number | undefined;
|
||||
readableAll?: boolean | undefined;
|
||||
writableAll?: boolean | undefined;
|
||||
}
|
||||
interface ServerOpts {
|
||||
/**
|
||||
* Indicates whether half-opened TCP connections are allowed.
|
||||
* @default false
|
||||
*/
|
||||
allowHalfOpen?: boolean | undefined;
|
||||
/**
|
||||
* Indicates whether the socket should be paused on incoming connections.
|
||||
* @default false
|
||||
*/
|
||||
pauseOnConnect?: boolean | undefined;
|
||||
/**
|
||||
* If set to `true`, it disables the use of Nagle's algorithm immediately after a new incoming connection is received.
|
||||
* @default false
|
||||
* @since v16.5.0
|
||||
*/
|
||||
noDelay?: boolean | undefined;
|
||||
/**
|
||||
* If set to `true`, it enables keep-alive functionality on the socket immediately after a new incoming connection is received,
|
||||
* similarly on what is done in `socket.setKeepAlive([enable][, initialDelay])`.
|
||||
* @default false
|
||||
* @since v16.5.0
|
||||
*/
|
||||
keepAlive?: boolean | undefined;
|
||||
/**
|
||||
* If set to a positive number, it sets the initial delay before the first keepalive probe is sent on an idle socket.
|
||||
* @default 0
|
||||
* @since v16.5.0
|
||||
*/
|
||||
keepAliveInitialDelay?: number | undefined;
|
||||
/**
|
||||
* Optionally overrides all `net.Socket`s' `readableHighWaterMark` and `writableHighWaterMark`.
|
||||
* @default See [stream.getDefaultHighWaterMark()](https://nodejs.org/docs/latest-v26.x/api/stream.html#streamgetdefaulthighwatermarkobjectmode).
|
||||
* @since v18.17.0, v20.1.0
|
||||
*/
|
||||
highWaterMark?: number | undefined;
|
||||
/**
|
||||
* `blockList` can be used for disabling inbound
|
||||
* access to specific IP addresses, IP ranges, or IP subnets. This does not
|
||||
* work if the server is behind a reverse proxy, NAT, etc. because the address
|
||||
* checked against the block list is the address of the proxy, or the one
|
||||
* specified by the NAT.
|
||||
* @since v22.13.0
|
||||
*/
|
||||
blockList?: BlockList | undefined;
|
||||
}
|
||||
interface DropArgument {
|
||||
localAddress?: string;
|
||||
localPort?: number;
|
||||
localFamily?: string;
|
||||
remoteAddress?: string;
|
||||
remotePort?: number;
|
||||
remoteFamily?: string;
|
||||
}
|
||||
interface ServerEventMap {
|
||||
"close": [];
|
||||
"connection": [socket: Socket];
|
||||
"error": [err: Error];
|
||||
"listening": [];
|
||||
"drop": [data?: DropArgument];
|
||||
}
|
||||
/**
|
||||
* This class is used to create a TCP or `IPC` server.
|
||||
* @since v0.1.90
|
||||
*/
|
||||
class Server implements EventEmitter {
|
||||
constructor(connectionListener?: (socket: Socket) => void);
|
||||
constructor(options?: ServerOpts, connectionListener?: (socket: Socket) => void);
|
||||
/**
|
||||
* Start a server listening for connections. A `net.Server` can be a TCP or
|
||||
* an `IPC` server depending on what it listens to.
|
||||
*
|
||||
* Possible signatures:
|
||||
*
|
||||
* * `server.listen(handle[, backlog][, callback])`
|
||||
* * `server.listen(options[, callback])`
|
||||
* * `server.listen(path[, backlog][, callback])` for `IPC` servers
|
||||
* * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
|
||||
*
|
||||
* This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
|
||||
* event.
|
||||
*
|
||||
* All `listen()` methods can take a `backlog` parameter to specify the maximum
|
||||
* length of the queue of pending connections. The actual length will be determined
|
||||
* by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512).
|
||||
*
|
||||
* All {@link Socket} are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
|
||||
* details).
|
||||
*
|
||||
* The `server.listen()` method can be called again if and only if there was an
|
||||
* error during the first `server.listen()` call or `server.close()` has been
|
||||
* called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
|
||||
*
|
||||
* One of the most common errors raised when listening is `EADDRINUSE`.
|
||||
* This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
|
||||
* after a certain amount of time:
|
||||
*
|
||||
* ```js
|
||||
* server.on('error', (e) => {
|
||||
* if (e.code === 'EADDRINUSE') {
|
||||
* console.error('Address in use, retrying...');
|
||||
* setTimeout(() => {
|
||||
* server.close();
|
||||
* server.listen(PORT, HOST);
|
||||
* }, 1000);
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;
|
||||
listen(port?: number, hostname?: string, listeningListener?: () => void): this;
|
||||
listen(port?: number, backlog?: number, listeningListener?: () => void): this;
|
||||
listen(port?: number, listeningListener?: () => void): this;
|
||||
listen(path: string, backlog?: number, listeningListener?: () => void): this;
|
||||
listen(path: string, listeningListener?: () => void): this;
|
||||
listen(options: ListenOptions, listeningListener?: () => void): this;
|
||||
listen(handle: any, backlog?: number, listeningListener?: () => void): this;
|
||||
listen(handle: any, listeningListener?: () => void): this;
|
||||
/**
|
||||
* Stops the server from accepting new connections and keeps existing
|
||||
* connections. This function is asynchronous, the server is finally closed
|
||||
* when all connections are ended and the server emits a `'close'` event.
|
||||
* The optional `callback` will be called once the `'close'` event occurs. Unlike
|
||||
* that event, it will be called with an `Error` as its only argument if the server
|
||||
* was not open when it was closed.
|
||||
* @since v0.1.90
|
||||
* @param callback Called when the server is closed.
|
||||
*/
|
||||
close(callback?: (err?: Error) => void): this;
|
||||
/**
|
||||
* Returns the bound `address`, the address `family` name, and `port` of the server
|
||||
* as reported by the operating system if listening on an IP socket
|
||||
* (useful to find which port was assigned when getting an OS-assigned address):`{ port: 12346, family: 'IPv4', address: '127.0.0.1' }`.
|
||||
*
|
||||
* For a server listening on a pipe or Unix domain socket, the name is returned
|
||||
* as a string.
|
||||
*
|
||||
* ```js
|
||||
* const server = net.createServer((socket) => {
|
||||
* socket.end('goodbye\n');
|
||||
* }).on('error', (err) => {
|
||||
* // Handle errors here.
|
||||
* throw err;
|
||||
* });
|
||||
*
|
||||
* // Grab an arbitrary unused port.
|
||||
* server.listen(() => {
|
||||
* console.log('opened server on', server.address());
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* `server.address()` returns `null` before the `'listening'` event has been
|
||||
* emitted or after calling `server.close()`.
|
||||
* @since v0.1.90
|
||||
*/
|
||||
address(): AddressInfo | string | null;
|
||||
/**
|
||||
* Asynchronously get the number of concurrent connections on the server. Works
|
||||
* when sockets were sent to forks.
|
||||
*
|
||||
* Callback should take two arguments `err` and `count`.
|
||||
* @since v0.9.7
|
||||
*/
|
||||
getConnections(cb: (error: Error | null, count: number) => void): this;
|
||||
/**
|
||||
* Opposite of `unref()`, calling `ref()` on a previously `unref`ed server will _not_ let the program exit if it's the only server left (the default behavior).
|
||||
* If the server is `ref`ed calling `ref()` again will have no effect.
|
||||
* @since v0.9.1
|
||||
*/
|
||||
ref(): this;
|
||||
/**
|
||||
* Calling `unref()` on a server will allow the program to exit if this is the only
|
||||
* active server in the event system. If the server is already `unref`ed calling`unref()` again will have no effect.
|
||||
* @since v0.9.1
|
||||
*/
|
||||
unref(): this;
|
||||
/**
|
||||
* Set this property to reject connections when the server's connection count gets
|
||||
* high.
|
||||
*
|
||||
* It is not recommended to use this option once a socket has been sent to a child
|
||||
* with `child_process.fork()`.
|
||||
* @since v0.2.0
|
||||
*/
|
||||
maxConnections: number;
|
||||
connections: number;
|
||||
/**
|
||||
* Indicates whether or not the server is listening for connections.
|
||||
* @since v5.7.0
|
||||
*/
|
||||
readonly listening: boolean;
|
||||
/**
|
||||
* Calls {@link Server.close()} and returns a promise that fulfills when the server has closed.
|
||||
* @since v20.5.0
|
||||
*/
|
||||
[Symbol.asyncDispose](): Promise<void>;
|
||||
}
|
||||
interface Server extends InternalEventEmitter<ServerEventMap> {}
|
||||
type IPVersion = "ipv4" | "ipv6";
|
||||
/**
|
||||
* The `BlockList` object can be used with some network APIs to specify rules for
|
||||
* disabling inbound or outbound access to specific IP addresses, IP ranges, or
|
||||
* IP subnets.
|
||||
* @since v15.0.0, v14.18.0
|
||||
*/
|
||||
class BlockList {
|
||||
/**
|
||||
* Adds a rule to block the given IP address.
|
||||
* @since v15.0.0, v14.18.0
|
||||
* @param address An IPv4 or IPv6 address.
|
||||
* @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`.
|
||||
*/
|
||||
addAddress(address: string, type?: IPVersion): void;
|
||||
addAddress(address: SocketAddress): void;
|
||||
/**
|
||||
* Adds a rule to block a range of IP addresses from `start` (inclusive) to`end` (inclusive).
|
||||
* @since v15.0.0, v14.18.0
|
||||
* @param start The starting IPv4 or IPv6 address in the range.
|
||||
* @param end The ending IPv4 or IPv6 address in the range.
|
||||
* @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`.
|
||||
*/
|
||||
addRange(start: string, end: string, type?: IPVersion): void;
|
||||
addRange(start: SocketAddress, end: SocketAddress): void;
|
||||
/**
|
||||
* Adds a rule to block a range of IP addresses specified as a subnet mask.
|
||||
* @since v15.0.0, v14.18.0
|
||||
* @param net The network IPv4 or IPv6 address.
|
||||
* @param prefix The number of CIDR prefix bits. For IPv4, this must be a value between `0` and `32`. For IPv6, this must be between `0` and `128`.
|
||||
* @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`.
|
||||
*/
|
||||
addSubnet(net: SocketAddress, prefix: number): void;
|
||||
addSubnet(net: string, prefix: number, type?: IPVersion): void;
|
||||
/**
|
||||
* Returns `true` if the given IP address matches any of the rules added to the`BlockList`.
|
||||
*
|
||||
* ```js
|
||||
* const blockList = new net.BlockList();
|
||||
* blockList.addAddress('123.123.123.123');
|
||||
* blockList.addRange('10.0.0.1', '10.0.0.10');
|
||||
* blockList.addSubnet('8592:757c:efae:4e45::', 64, 'ipv6');
|
||||
*
|
||||
* console.log(blockList.check('123.123.123.123')); // Prints: true
|
||||
* console.log(blockList.check('10.0.0.3')); // Prints: true
|
||||
* console.log(blockList.check('222.111.111.222')); // Prints: false
|
||||
*
|
||||
* // IPv6 notation for IPv4 addresses works:
|
||||
* console.log(blockList.check('::ffff:7b7b:7b7b', 'ipv6')); // Prints: true
|
||||
* console.log(blockList.check('::ffff:123.123.123.123', 'ipv6')); // Prints: true
|
||||
* ```
|
||||
* @since v15.0.0, v14.18.0
|
||||
* @param address The IP address to check
|
||||
* @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`.
|
||||
*/
|
||||
check(address: SocketAddress): boolean;
|
||||
check(address: string, type?: IPVersion): boolean;
|
||||
/**
|
||||
* The list of rules added to the blocklist.
|
||||
* @since v15.0.0, v14.18.0
|
||||
*/
|
||||
rules: readonly string[];
|
||||
/**
|
||||
* Returns `true` if the `value` is a `net.BlockList`.
|
||||
* @since v22.13.0
|
||||
* @param value Any JS value
|
||||
*/
|
||||
static isBlockList(value: unknown): value is BlockList;
|
||||
/**
|
||||
* ```js
|
||||
* const blockList = new net.BlockList();
|
||||
* const data = [
|
||||
* 'Subnet: IPv4 192.168.1.0/24',
|
||||
* 'Address: IPv4 10.0.0.5',
|
||||
* 'Range: IPv4 192.168.2.1-192.168.2.10',
|
||||
* 'Range: IPv4 10.0.0.1-10.0.0.10',
|
||||
* ];
|
||||
* blockList.fromJSON(data);
|
||||
* blockList.fromJSON(JSON.stringify(data));
|
||||
* ```
|
||||
* @since v24.5.0
|
||||
* @experimental
|
||||
*/
|
||||
fromJSON(data: string | readonly string[]): void;
|
||||
/**
|
||||
* @since v24.5.0
|
||||
* @experimental
|
||||
*/
|
||||
toJSON(): readonly string[];
|
||||
}
|
||||
interface TcpNetConnectOpts extends TcpSocketConnectOpts, SocketConstructorOpts {
|
||||
timeout?: number | undefined;
|
||||
}
|
||||
interface IpcNetConnectOpts extends IpcSocketConnectOpts, SocketConstructorOpts {
|
||||
timeout?: number | undefined;
|
||||
}
|
||||
type NetConnectOpts = TcpNetConnectOpts | IpcNetConnectOpts;
|
||||
/**
|
||||
* Creates a new TCP or `IPC` server.
|
||||
*
|
||||
* If `allowHalfOpen` is set to `true`, when the other end of the socket
|
||||
* signals the end of transmission, the server will only send back the end of
|
||||
* transmission when `socket.end()` is explicitly called. For example, in the
|
||||
* context of TCP, when a FIN packed is received, a FIN packed is sent
|
||||
* back only when `socket.end()` is explicitly called. Until then the
|
||||
* connection is half-closed (non-readable but still writable). See `'end'` event and [RFC 1122](https://tools.ietf.org/html/rfc1122) (section 4.2.2.13) for more information.
|
||||
*
|
||||
* If `pauseOnConnect` is set to `true`, then the socket associated with each
|
||||
* incoming connection will be paused, and no data will be read from its handle.
|
||||
* This allows connections to be passed between processes without any data being
|
||||
* read by the original process. To begin reading data from a paused socket, call `socket.resume()`.
|
||||
*
|
||||
* The server can be a TCP server or an `IPC` server, depending on what it `listen()` to.
|
||||
*
|
||||
* Here is an example of a TCP echo server which listens for connections
|
||||
* on port 8124:
|
||||
*
|
||||
* ```js
|
||||
* import net from 'node:net';
|
||||
* const server = net.createServer((c) => {
|
||||
* // 'connection' listener.
|
||||
* console.log('client connected');
|
||||
* c.on('end', () => {
|
||||
* console.log('client disconnected');
|
||||
* });
|
||||
* c.write('hello\r\n');
|
||||
* c.pipe(c);
|
||||
* });
|
||||
* server.on('error', (err) => {
|
||||
* throw err;
|
||||
* });
|
||||
* server.listen(8124, () => {
|
||||
* console.log('server bound');
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Test this by using `telnet`:
|
||||
*
|
||||
* ```bash
|
||||
* telnet localhost 8124
|
||||
* ```
|
||||
*
|
||||
* To listen on the socket `/tmp/echo.sock`:
|
||||
*
|
||||
* ```js
|
||||
* server.listen('/tmp/echo.sock', () => {
|
||||
* console.log('server bound');
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Use `nc` to connect to a Unix domain socket server:
|
||||
*
|
||||
* ```bash
|
||||
* nc -U /tmp/echo.sock
|
||||
* ```
|
||||
* @since v0.5.0
|
||||
* @param connectionListener Automatically set as a listener for the {@link 'connection'} event.
|
||||
*/
|
||||
function createServer(connectionListener?: (socket: Socket) => void): Server;
|
||||
function createServer(options?: ServerOpts, connectionListener?: (socket: Socket) => void): Server;
|
||||
/**
|
||||
* Aliases to {@link createConnection}.
|
||||
*
|
||||
* Possible signatures:
|
||||
*
|
||||
* * {@link connect}
|
||||
* * {@link connect} for `IPC` connections.
|
||||
* * {@link connect} for TCP connections.
|
||||
*/
|
||||
function connect(options: NetConnectOpts, connectionListener?: () => void): Socket;
|
||||
function connect(port: number, host?: string, connectionListener?: () => void): Socket;
|
||||
function connect(path: string, connectionListener?: () => void): Socket;
|
||||
/**
|
||||
* A factory function, which creates a new {@link Socket},
|
||||
* immediately initiates connection with `socket.connect()`,
|
||||
* then returns the `net.Socket` that starts the connection.
|
||||
*
|
||||
* When the connection is established, a `'connect'` event will be emitted
|
||||
* on the returned socket. The last parameter `connectListener`, if supplied,
|
||||
* will be added as a listener for the `'connect'` event **once**.
|
||||
*
|
||||
* Possible signatures:
|
||||
*
|
||||
* * {@link createConnection}
|
||||
* * {@link createConnection} for `IPC` connections.
|
||||
* * {@link createConnection} for TCP connections.
|
||||
*
|
||||
* The {@link connect} function is an alias to this function.
|
||||
*/
|
||||
function createConnection(options: NetConnectOpts, connectionListener?: () => void): Socket;
|
||||
function createConnection(port: number, host?: string, connectionListener?: () => void): Socket;
|
||||
function createConnection(path: string, connectionListener?: () => void): Socket;
|
||||
/**
|
||||
* Gets the current default value of the `autoSelectFamily` option of `socket.connect(options)`.
|
||||
* The initial default value is `true`, unless the command line option`--no-network-family-autoselection` is provided.
|
||||
* @since v19.4.0
|
||||
*/
|
||||
function getDefaultAutoSelectFamily(): boolean;
|
||||
/**
|
||||
* Sets the default value of the `autoSelectFamily` option of `socket.connect(options)`.
|
||||
* @param value The new default value.
|
||||
* The initial default value is `true`, unless the command line option
|
||||
* `--no-network-family-autoselection` is provided.
|
||||
* @since v19.4.0
|
||||
*/
|
||||
function setDefaultAutoSelectFamily(value: boolean): void;
|
||||
/**
|
||||
* Gets the current default value of the `autoSelectFamilyAttemptTimeout` option of `socket.connect(options)`.
|
||||
* The initial default value is `500` or the value specified via the command line option `--network-family-autoselection-attempt-timeout`.
|
||||
* @returns The current default value of the `autoSelectFamilyAttemptTimeout` option.
|
||||
* @since v19.8.0, v18.8.0
|
||||
*/
|
||||
function getDefaultAutoSelectFamilyAttemptTimeout(): number;
|
||||
/**
|
||||
* Sets the default value of the `autoSelectFamilyAttemptTimeout` option of `socket.connect(options)`.
|
||||
* @param value The new default value, which must be a positive number. If the number is less than `10`, the value `10` is used instead. The initial default value is `250` or the value specified via the command line
|
||||
* option `--network-family-autoselection-attempt-timeout`.
|
||||
* @since v19.8.0, v18.8.0
|
||||
*/
|
||||
function setDefaultAutoSelectFamilyAttemptTimeout(value: number): void;
|
||||
/**
|
||||
* Returns `6` if `input` is an IPv6 address. Returns `4` if `input` is an IPv4
|
||||
* address in [dot-decimal notation](https://en.wikipedia.org/wiki/Dot-decimal_notation) with no leading zeroes. Otherwise, returns`0`.
|
||||
*
|
||||
* ```js
|
||||
* net.isIP('::1'); // returns 6
|
||||
* net.isIP('127.0.0.1'); // returns 4
|
||||
* net.isIP('127.000.000.001'); // returns 0
|
||||
* net.isIP('127.0.0.1/24'); // returns 0
|
||||
* net.isIP('fhqwhgads'); // returns 0
|
||||
* ```
|
||||
* @since v0.3.0
|
||||
*/
|
||||
function isIP(input: string): number;
|
||||
/**
|
||||
* Returns `true` if `input` is an IPv4 address in [dot-decimal notation](https://en.wikipedia.org/wiki/Dot-decimal_notation) with no
|
||||
* leading zeroes. Otherwise, returns `false`.
|
||||
*
|
||||
* ```js
|
||||
* net.isIPv4('127.0.0.1'); // returns true
|
||||
* net.isIPv4('127.000.000.001'); // returns false
|
||||
* net.isIPv4('127.0.0.1/24'); // returns false
|
||||
* net.isIPv4('fhqwhgads'); // returns false
|
||||
* ```
|
||||
* @since v0.3.0
|
||||
*/
|
||||
function isIPv4(input: string): boolean;
|
||||
/**
|
||||
* Returns `true` if `input` is an IPv6 address. Otherwise, returns `false`.
|
||||
*
|
||||
* ```js
|
||||
* net.isIPv6('::1'); // returns true
|
||||
* net.isIPv6('fhqwhgads'); // returns false
|
||||
* ```
|
||||
* @since v0.3.0
|
||||
*/
|
||||
function isIPv6(input: string): boolean;
|
||||
interface SocketAddressInitOptions {
|
||||
/**
|
||||
* The network address as either an IPv4 or IPv6 string.
|
||||
* @default 127.0.0.1
|
||||
*/
|
||||
address?: string | undefined;
|
||||
/**
|
||||
* @default `'ipv4'`
|
||||
*/
|
||||
family?: IPVersion | undefined;
|
||||
/**
|
||||
* An IPv6 flow-label used only if `family` is `'ipv6'`.
|
||||
* @default 0
|
||||
*/
|
||||
flowlabel?: number | undefined;
|
||||
/**
|
||||
* An IP port.
|
||||
* @default 0
|
||||
*/
|
||||
port?: number | undefined;
|
||||
}
|
||||
/**
|
||||
* @since v15.14.0, v14.18.0
|
||||
*/
|
||||
class SocketAddress {
|
||||
constructor(options: SocketAddressInitOptions);
|
||||
/**
|
||||
* Either \`'ipv4'\` or \`'ipv6'\`.
|
||||
* @since v15.14.0, v14.18.0
|
||||
*/
|
||||
readonly address: string;
|
||||
/**
|
||||
* Either \`'ipv4'\` or \`'ipv6'\`.
|
||||
* @since v15.14.0, v14.18.0
|
||||
*/
|
||||
readonly family: IPVersion;
|
||||
/**
|
||||
* @since v15.14.0, v14.18.0
|
||||
*/
|
||||
readonly port: number;
|
||||
/**
|
||||
* @since v15.14.0, v14.18.0
|
||||
*/
|
||||
readonly flowlabel: number;
|
||||
/**
|
||||
* @since v22.13.0
|
||||
* @param input An input string containing an IP address and optional port,
|
||||
* e.g. `123.1.2.3:1234` or `[1::1]:1234`.
|
||||
* @returns Returns a `SocketAddress` if parsing was successful.
|
||||
* Otherwise returns `undefined`.
|
||||
*/
|
||||
static parse(input: string): SocketAddress | undefined;
|
||||
}
|
||||
}
|
||||
declare module "net" {
|
||||
export * from "node:net";
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/ast/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAM/C,IAAI,eAAgD,CAAC;AACrD,SAAS,kBAAkB;IACvB,IAAI,CAAC,eAAe,EAAE,CAAC;QACnB,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACzC,MAAM,GAAG,GAAG,UAAU,CAAC,IAA+B,CAAC,CAAC;YACxD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvD,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,CAAC;QACL,CAAC;QACD,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,eAAe,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAgB;IAC7C,OAAO,kBAAkB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,WAAW,IAAI,GAAG,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,UAAoB;IAC3D,MAAM,EAAE,GAAG,UAAoB,CAAC;IAChC,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC;QAC5I,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,EAAE,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,UAAkB;IACvD,OAAO,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC;QAC5H,CAAC,CAAC,GAAG,GAAG,UAAU;QAClB,CAAC,CAAC,UAAU,CAAa,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,OAAO,CAA8B,KAAsB,EAAE,IAAmC;IAC5G,OAAO,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,IAAI,CAA8B,KAAsB,EAAE,IAAmC;IACzG,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAErD,MAAM,IAAI,KAAK,CAAC,oCAAoC,KAAK,2BAA2B,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;AACvG,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,UAAsB;IACtD,OAAO;QACH,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,cAAc,EAAE,UAAU,CAAC,cAAc;QACzC,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,eAAe,EAAE,UAAU,CAAC,eAAe;QAC3C,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,iBAAiB,EAAE,UAAU,CAAC,iBAAiB;QAC/C,eAAe,EAAE,UAAU,CAAC,eAAe;QAC3C,uBAAuB,EAAE,UAAU,CAAC,uBAAuB;QAC3D,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;QACzD,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,mBAAmB,EAAE,UAAU,CAAC,mBAAmB;QACnD,kBAAkB,EAAE,UAAU,CAAC,kBAAkB;QACjD,uBAAuB,EAAE,UAAU,CAAC,uBAAuB;QAC3D,UAAU,EAAE,SAAS;KACxB,CAAC;AACN,CAAC"}
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_interop_require_wildcard.js";
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"blake2b.d.ts","sourceRoot":"","sources":["../src/blake2b.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,aAAa,CAAC;AAC7D,+DAA+D;AAC/D,eAAO,MAAM,OAAO,EAAE,OAAO,GAAS,CAAC;AACvC,+DAA+D;AAC/D,eAAO,MAAM,OAAO,EAAE,OAAO,GAAS,CAAC"}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/ast/clone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAQ/C,OAAO,EACH,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,mBAAmB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,SAAS,OAAO,CAAC,KAAU;IACvB,4DAA4D;IAC5D,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,uBAAuB,CAAI,QAAc,EAAE,MAA4D,EAAE,OAA0E;IACxL,MAAM,KAAK,GAA+B,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAW,EAAE,CAAC,CAAC,iDAAiD;IAC7E,OAAO,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAG,CAAC;QAC9B,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnB,IAAI,OAAO,EAAE,CAAC;gBACV,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACrC,IAAI,GAAG,EAAE,CAAC;oBACN,IAAI,GAAG,KAAK,MAAM;wBAAE,SAAS;oBAC7B,OAAO,GAAG,CAAC;gBACf,CAAC;YACL,CAAC;YACD,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC3C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC;QACL,CAAC;aACI,CAAC;YACF,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACpC,IAAI,GAAG,EAAE,CAAC;gBACN,IAAI,GAAG,KAAK,MAAM;oBAAE,SAAS;gBAC7B,OAAO,GAAG,CAAC;YACf,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;gBACvC,+EAA+E;gBAC/E,KAAK,MAAM,KAAK,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;oBAClD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAClB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC1B,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAU;IACtC,MAAM,QAAQ,GAA+B,EAAE,CAAC;IAChD,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,yFAAyF;IACtI,OAAO,QAAQ,CAAC;IAEhB,SAAS,WAAW,CAAC,CAAyB;QAC1C,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAiB,QAAuB;IAC/D,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC5C,uBAAuB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QAC/C,KAAa,CAAC,MAAM,GAAG,MAAM,CAAC;QAC/B,OAAO,SAAS,CAAC;IACrB,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAS,YAAY,CAAiB,IAAO,EAAE,KAAoC;IAC/E,IAAI,KAAK,EAAE,CAAC;QACP,IAAY,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QAC7B,IAAY,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAWD,MAAM,UAAU,uBAAuB,CAAiB,IAAmB,EAAE,aAAa,GAAG,IAAI;IAC7F,MAAM,KAAK,GAAG,IAAI,IAAI,6BAA6B,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;QACzB,KAAa,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QACvB,KAAa,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC;AAOD,MAAM,UAAU,wBAAwB,CAAiB,KAA+B,EAAE,aAAa,GAAG,IAAI;IAC1G,IAAI,KAAK,EAAE,CAAC;QACR,MAAM,MAAM,GAAG,eAAe,CAC1B,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,EACzD,KAAK,CAAC,GAAG,EACT,KAAK,CAAC,GAAG,CACZ,CAAC;QACF,OAAO,MAAM,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,6BAA6B,CAAiB,IAAO;IAC1D,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5E,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,iFAAiF;QACjF,kCAAkC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,aAAa;YAChD,CAAC,CAAC,mBAAmB,CAAE,IAA8B,CAAC,IAAI,EAAG,IAA8B,CAAC,UAAU,CAAc;YACpH,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,cAAc;gBACzC,CAAC,CAAC,oBAAoB,CAAE,IAA+B,CAAC,IAAI,EAAG,IAA+B,CAAC,UAAU,CAAc;gBACvH,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,mEAAmE;IACnE,+DAA+D;IAC9D,OAAe,CAAC,MAAM,GAAG,SAAU,CAAC;IACrC,OAAO,OAAO,CAAC;AACnB,CAAC"}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "module",
|
||||
"main": "./index.cjs",
|
||||
"module": "./index.js",
|
||||
"types": "./index.d.cts",
|
||||
"sideEffects": false
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*! *****************************************************************************
|
||||
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"/>
|
||||
|
||||
interface WeakRef<T extends WeakKey> {
|
||||
readonly [Symbol.toStringTag]: "WeakRef";
|
||||
|
||||
/**
|
||||
* Returns the WeakRef instance's target value, or undefined if the target value has been
|
||||
* reclaimed.
|
||||
* In es2023 the value can be either a symbol or an object, in previous versions only object is permissible.
|
||||
*/
|
||||
deref(): T | undefined;
|
||||
}
|
||||
|
||||
interface WeakRefConstructor {
|
||||
readonly prototype: WeakRef<any>;
|
||||
|
||||
/**
|
||||
* Creates a WeakRef instance for the given target value.
|
||||
* In es2023 the value can be either a symbol or an object, in previous versions only object is permissible.
|
||||
* @param target The target value for the WeakRef instance.
|
||||
*/
|
||||
new <T extends WeakKey>(target: T): WeakRef<T>;
|
||||
}
|
||||
|
||||
declare var WeakRef: WeakRefConstructor;
|
||||
|
||||
interface FinalizationRegistry<T> {
|
||||
readonly [Symbol.toStringTag]: "FinalizationRegistry";
|
||||
|
||||
/**
|
||||
* Registers a value with the registry.
|
||||
* In es2023 the value can be either a symbol or an object, in previous versions only object is permissible.
|
||||
* @param target The target value to register.
|
||||
* @param heldValue The value to pass to the finalizer for this value. This cannot be the
|
||||
* target value.
|
||||
* @param unregisterToken The token to pass to the unregister method to unregister the target
|
||||
* value. If not provided, the target cannot be unregistered.
|
||||
*/
|
||||
register(target: WeakKey, heldValue: T, unregisterToken?: WeakKey): void;
|
||||
|
||||
/**
|
||||
* Unregisters a value from the registry.
|
||||
* In es2023 the value can be either a symbol or an object, in previous versions only object is permissible.
|
||||
* @param unregisterToken The token that was used as the unregisterToken argument when calling
|
||||
* register to register the target value.
|
||||
*/
|
||||
unregister(unregisterToken: WeakKey): boolean;
|
||||
}
|
||||
|
||||
interface FinalizationRegistryConstructor {
|
||||
readonly prototype: FinalizationRegistry<any>;
|
||||
|
||||
/**
|
||||
* Creates a finalization registry with an associated cleanup callback
|
||||
* @param cleanupCallback The callback to call after a value in the registry has been reclaimed.
|
||||
*/
|
||||
new <T>(cleanupCallback: (heldValue: T) => void): FinalizationRegistry<T>;
|
||||
}
|
||||
|
||||
declare var FinalizationRegistry: FinalizationRegistryConstructor;
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2018_intl = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2018_intl = {
|
||||
libs: [],
|
||||
variables: [['Intl', base_config_1.TYPE_VALUE]],
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
# PostCSS
|
||||
|
||||
<img align="right" width="95" height="95"
|
||||
alt="Philosopher’s stone, logo of PostCSS"
|
||||
src="https://postcss.org/logo.svg">
|
||||
|
||||
PostCSS is a tool for transforming styles with JS plugins.
|
||||
These plugins can lint your CSS, support variables and mixins,
|
||||
transpile future CSS syntax, inline images, and more.
|
||||
|
||||
PostCSS is used by industry leaders including Wikipedia, Twitter, Alibaba,
|
||||
and JetBrains. The [Autoprefixer] and [Stylelint] PostCSS plugins are some of the most popular CSS tools.
|
||||
|
||||
---
|
||||
|
||||
<img src="https://cdn.evilmartians.com/badges/logo-no-label.svg" alt="" width="22" height="16" /> PostCSS is built by <b><a href="https://evilmartians.com/">Evil Martians</a></b>, an American design and engineering consultancy for <b>developer tools, AI, and cybersecurity startups</b>.
|
||||
|
||||
---
|
||||
|
||||
[Abstract Syntax Tree]: https://en.wikipedia.org/wiki/Abstract_syntax_tree
|
||||
[Evil Martians]: https://evilmartians.com/?utm_source=postcss
|
||||
[Autoprefixer]: https://github.com/postcss/autoprefixer
|
||||
[Stylelint]: https://stylelint.io/
|
||||
[plugins]: https://github.com/postcss/postcss#plugins
|
||||
|
||||
## Docs
|
||||
Read full docs **[here](https://postcss.org/)**.
|
||||
@@ -0,0 +1,35 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const { join } = require('path')
|
||||
const { file } = require('./helper')
|
||||
const { createReadStream } = require('fs')
|
||||
const ThreadStream = require('..')
|
||||
const buffer = require('buffer')
|
||||
|
||||
const MAX_STRING = buffer.constants.MAX_STRING_LENGTH
|
||||
|
||||
test('string limit 2', { skip: process.env.CI }, (t, done) => {
|
||||
const dest = file()
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'to-file.js'),
|
||||
workerData: { dest },
|
||||
sync: false
|
||||
})
|
||||
|
||||
stream.on('close', async () => {
|
||||
let buf
|
||||
for await (const chunk of createReadStream(dest)) {
|
||||
buf = chunk
|
||||
}
|
||||
assert.strictEqual('asd', buf.toString().slice(-3))
|
||||
done()
|
||||
})
|
||||
|
||||
stream.on('ready', () => {
|
||||
stream.write('a'.repeat(MAX_STRING - 2))
|
||||
stream.write('asd')
|
||||
stream.end()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,852 @@
|
||||
/*
|
||||
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import estraverse from "estraverse";
|
||||
|
||||
import Reference from "./reference.js";
|
||||
import Variable from "./variable.js";
|
||||
import { Definition } from "./definition.js";
|
||||
import { assert } from "./assert.js";
|
||||
|
||||
/** @import * as types from "eslint-scope" */
|
||||
/** @import ESTree from "estree" */
|
||||
/** @import ScopeManager from "./scope-manager.js" */
|
||||
/** @typedef {ESTree.Function | ESTree.Program | ESTree.StaticBlock} Block */
|
||||
/** @typedef {{pattern: unknown, node: unknown}} MaybeImplicitGlobal */
|
||||
|
||||
const { Syntax } = estraverse;
|
||||
|
||||
/**
|
||||
* Test if scope is struct
|
||||
* @param {Scope} scope scope
|
||||
* @param {Block} block block
|
||||
* @param {boolean} isMethodDefinition is method definition
|
||||
* @returns {boolean} is strict scope
|
||||
*/
|
||||
function isStrictScope(scope, block, isMethodDefinition) {
|
||||
let body;
|
||||
|
||||
// When upper scope is exists and strict, inner scope is also strict.
|
||||
if (scope.upper && scope.upper.isStrict) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isMethodDefinition) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (scope.type === "class" || scope.type === "module") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (scope.type === "block" || scope.type === "switch") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scope.type === "function") {
|
||||
if (
|
||||
block.type === Syntax.ArrowFunctionExpression &&
|
||||
// @ts-ignore -- when block is ArrowFunctionExpression
|
||||
block.body.type !== Syntax.BlockStatement
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (block.type === Syntax.Program) {
|
||||
body = block;
|
||||
} else {
|
||||
body = block.body;
|
||||
}
|
||||
|
||||
if (!body) {
|
||||
return false;
|
||||
}
|
||||
} else if (scope.type === "global") {
|
||||
body = block;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Search for a 'use strict' directive.
|
||||
// @ts-ignore -- body is a function body
|
||||
for (let i = 0, iz = body.body.length; i < iz; ++i) {
|
||||
// @ts-ignore -- body is a function body
|
||||
const stmt = body.body[i];
|
||||
|
||||
/*
|
||||
* Check if the current statement is a directive.
|
||||
* If it isn't, then we're past the directive prologue
|
||||
* so stop the search because directives cannot
|
||||
* appear after this point.
|
||||
*
|
||||
* Some parsers set `directive:null` on non-directive
|
||||
* statements, so the `typeof` check is safer than
|
||||
* checking for property existence.
|
||||
*/
|
||||
if (typeof stmt.directive !== "string") {
|
||||
break;
|
||||
}
|
||||
|
||||
if (stmt.directive === "use strict") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register scope
|
||||
* @param {ScopeManager} scopeManager scope manager
|
||||
* @param {Scope} scope scope
|
||||
* @returns {void}
|
||||
*/
|
||||
function registerScope(scopeManager, scope) {
|
||||
scopeManager.scopes.push(scope);
|
||||
|
||||
const scopes = scopeManager.__nodeToScope.get(scope.block);
|
||||
|
||||
if (scopes) {
|
||||
scopes.push(scope);
|
||||
} else {
|
||||
scopeManager.__nodeToScope.set(scope.block, [scope]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor Scope
|
||||
* @implements {types.Scope}
|
||||
*/
|
||||
class Scope {
|
||||
constructor(scopeManager, type, upperScope, block, isMethodDefinition) {
|
||||
/**
|
||||
* One of "global", "module", "function", "function-expression-name", "block", "switch", "catch", "with", "for",
|
||||
* "class", "class-field-initializer", "class-static-block".
|
||||
* @member {string} Scope#type
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* The scoped {@link Variable}s of this scope, as <code>{ Variable.name
|
||||
* : Variable }</code>.
|
||||
* @member {Map} Scope#set
|
||||
*/
|
||||
this.set = new Map();
|
||||
|
||||
/**
|
||||
* The tainted variables of this scope, as <code>{ Variable.name :
|
||||
* boolean }</code>.
|
||||
* @member {Map} Scope#taints
|
||||
*/
|
||||
this.taints = new Map();
|
||||
|
||||
/**
|
||||
* Generally, through the lexical scoping of JS you can always know
|
||||
* which variable an identifier in the source code refers to. There are
|
||||
* a few exceptions to this rule. With 'global' and 'with' scopes you
|
||||
* can only decide at runtime which variable a reference refers to.
|
||||
* Moreover, if 'eval()' is used in a scope, it might introduce new
|
||||
* bindings in this or its parent scopes.
|
||||
* All those scopes are considered 'dynamic'.
|
||||
* @member {boolean} Scope#dynamic
|
||||
*/
|
||||
this.dynamic = this.type === "global" || this.type === "with";
|
||||
|
||||
/**
|
||||
* A reference to the scope-defining syntax node.
|
||||
* @member {espree.Node} Scope#block
|
||||
*/
|
||||
this.block = block;
|
||||
|
||||
/**
|
||||
* The {@link Reference|references} that are not resolved with this scope.
|
||||
* @member {Reference[]} Scope#through
|
||||
*/
|
||||
this.through = [];
|
||||
|
||||
/**
|
||||
* The scoped {@link Variable}s of this scope. In the case of a
|
||||
* 'function' scope this includes the automatic argument <em>arguments</em> as
|
||||
* its first element, as well as all further formal arguments.
|
||||
* @member {Variable[]} Scope#variables
|
||||
*/
|
||||
this.variables = [];
|
||||
|
||||
/**
|
||||
* Any variable {@link Reference|reference} found in this scope. This
|
||||
* includes occurrences of local variables as well as variables from
|
||||
* parent scopes (including the global scope). For local variables
|
||||
* this also includes defining occurrences (like in a 'var' statement).
|
||||
* In a 'function' scope this does not include the occurrences of the
|
||||
* formal parameter in the parameter list.
|
||||
* @member {Reference[]} Scope#references
|
||||
*/
|
||||
this.references = [];
|
||||
|
||||
/**
|
||||
* For 'global' and 'function' scopes, this is a self-reference. For
|
||||
* other scope types this is the <em>variableScope</em> value of the
|
||||
* parent scope.
|
||||
* @member {Scope} Scope#variableScope
|
||||
*/
|
||||
this.variableScope =
|
||||
this.type === "global" ||
|
||||
this.type === "module" ||
|
||||
this.type === "function" ||
|
||||
this.type === "class-field-initializer" ||
|
||||
this.type === "class-static-block"
|
||||
? this
|
||||
: upperScope.variableScope;
|
||||
|
||||
/**
|
||||
* Whether this scope is created by a FunctionExpression.
|
||||
* @member {boolean} Scope#functionExpressionScope
|
||||
*/
|
||||
this.functionExpressionScope = /** @type {any} */ (false);
|
||||
|
||||
/**
|
||||
* Whether this is a scope that contains an 'eval()' invocation.
|
||||
* @member {boolean} Scope#directCallToEvalScope
|
||||
*/
|
||||
this.directCallToEvalScope = false;
|
||||
|
||||
/**
|
||||
* @member {boolean} Scope#thisFound
|
||||
*/
|
||||
this.thisFound = false;
|
||||
|
||||
/** @type {?Reference[]} */
|
||||
this.__left = [];
|
||||
|
||||
/**
|
||||
* Reference to the parent {@link Scope|scope}.
|
||||
* @member {Scope} Scope#upper
|
||||
*/
|
||||
this.upper = upperScope;
|
||||
|
||||
/**
|
||||
* Whether 'use strict' is in effect in this scope.
|
||||
* @member {boolean} Scope#isStrict
|
||||
*/
|
||||
this.isStrict = scopeManager.isStrictModeSupported()
|
||||
? isStrictScope(this, block, isMethodDefinition)
|
||||
: false;
|
||||
|
||||
/**
|
||||
* List of nested {@link Scope}s.
|
||||
* @member {Scope[]} Scope#childScopes
|
||||
*/
|
||||
this.childScopes = [];
|
||||
if (this.upper) {
|
||||
this.upper.childScopes.push(this);
|
||||
}
|
||||
|
||||
this.__declaredVariables = scopeManager.__declaredVariables;
|
||||
|
||||
registerScope(scopeManager, this);
|
||||
}
|
||||
|
||||
__shouldStaticallyClose(scopeManager) {
|
||||
return (
|
||||
!this.dynamic ||
|
||||
scopeManager.__isOptimistic() ||
|
||||
this.type === "global"
|
||||
);
|
||||
}
|
||||
|
||||
__staticCloseRef(ref) {
|
||||
if (!this.__resolve(ref)) {
|
||||
this.__delegateToUpperScope(ref);
|
||||
}
|
||||
}
|
||||
|
||||
__dynamicCloseRef(ref) {
|
||||
// notify all names are through to global
|
||||
let current = this;
|
||||
|
||||
do {
|
||||
current.through.push(ref);
|
||||
current = current.upper;
|
||||
} while (current);
|
||||
}
|
||||
|
||||
__close(scopeManager) {
|
||||
let closeRef;
|
||||
|
||||
if (this.__shouldStaticallyClose(scopeManager)) {
|
||||
closeRef = this.__staticCloseRef;
|
||||
} else {
|
||||
closeRef = this.__dynamicCloseRef;
|
||||
}
|
||||
|
||||
// Try Resolving all references in this scope.
|
||||
// @ts-ignore -- __left should be an array here
|
||||
for (let i = 0, iz = this.__left.length; i < iz; ++i) {
|
||||
// @ts-ignore -- __left should be an array here
|
||||
const ref = this.__left[i];
|
||||
|
||||
closeRef.call(this, ref);
|
||||
}
|
||||
this.__left = null;
|
||||
|
||||
return this.upper;
|
||||
}
|
||||
|
||||
// To override by function scopes.
|
||||
// References in default parameters isn't resolved to variables which are in their function body.
|
||||
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- Desired as instance method with signature
|
||||
__isValidResolution(ref, variable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
__resolve(ref) {
|
||||
const name = ref.identifier.name;
|
||||
|
||||
if (!this.set.has(name)) {
|
||||
return false;
|
||||
}
|
||||
const variable = this.set.get(name);
|
||||
|
||||
if (!this.__isValidResolution(ref, variable)) {
|
||||
return false;
|
||||
}
|
||||
variable.references.push(ref);
|
||||
variable.stack =
|
||||
variable.stack && ref.from.variableScope === this.variableScope;
|
||||
if (ref.tainted) {
|
||||
variable.tainted = true;
|
||||
this.taints.set(variable.name, true);
|
||||
}
|
||||
ref.resolved = variable;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__delegateToUpperScope(ref) {
|
||||
if (this.upper) {
|
||||
this.upper.__left.push(ref);
|
||||
}
|
||||
this.through.push(ref);
|
||||
}
|
||||
|
||||
__addDeclaredVariablesOfNode(variable, node) {
|
||||
if (node === null || node === void 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let variables = this.__declaredVariables.get(node);
|
||||
|
||||
if (variables === null || variables === void 0) {
|
||||
variables = [];
|
||||
this.__declaredVariables.set(node, variables);
|
||||
}
|
||||
if (!variables.includes(variable)) {
|
||||
variables.push(variable);
|
||||
}
|
||||
}
|
||||
|
||||
__defineGeneric(name, set, variables, node, def) {
|
||||
let variable;
|
||||
|
||||
variable = set.get(name);
|
||||
if (!variable) {
|
||||
variable = new Variable(name, this);
|
||||
set.set(name, variable);
|
||||
variables.push(variable);
|
||||
}
|
||||
|
||||
if (def) {
|
||||
variable.defs.push(def);
|
||||
this.__addDeclaredVariablesOfNode(variable, def.node);
|
||||
this.__addDeclaredVariablesOfNode(variable, def.parent);
|
||||
}
|
||||
if (node) {
|
||||
variable.identifiers.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
__define(node, def) {
|
||||
if (node && node.type === Syntax.Identifier) {
|
||||
this.__defineGeneric(
|
||||
node.name,
|
||||
this.set,
|
||||
this.variables,
|
||||
node,
|
||||
def,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
__referencing(node, assign, writeExpr, maybeImplicitGlobal, partial, init) {
|
||||
// because Array element may be null
|
||||
if (
|
||||
!node ||
|
||||
(node.type !== Syntax.Identifier && node.type !== "JSXIdentifier")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Specially handle like `this`.
|
||||
if (node.name === "super") {
|
||||
return;
|
||||
}
|
||||
|
||||
const ref = new Reference(
|
||||
node,
|
||||
this,
|
||||
assign || Reference.READ,
|
||||
writeExpr,
|
||||
maybeImplicitGlobal,
|
||||
!!partial,
|
||||
!!init,
|
||||
);
|
||||
|
||||
this.references.push(ref);
|
||||
|
||||
// @ts-ignore -- __left should be an array here
|
||||
this.__left.push(ref);
|
||||
}
|
||||
|
||||
__detectEval() {
|
||||
let current = this;
|
||||
|
||||
this.directCallToEvalScope = true;
|
||||
do {
|
||||
current.dynamic = true;
|
||||
current = current.upper;
|
||||
} while (current);
|
||||
}
|
||||
|
||||
__detectThis() {
|
||||
this.thisFound = true;
|
||||
}
|
||||
|
||||
__isClosed() {
|
||||
return this.__left === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns resolved {Reference}
|
||||
* @function Scope#resolve
|
||||
* @param {ESTree.Identifier} ident identifier to be resolved.
|
||||
* @returns {?Reference} reference
|
||||
*/
|
||||
resolve(ident) {
|
||||
let ref, i, iz;
|
||||
|
||||
assert(this.__isClosed(), "Scope should be closed.");
|
||||
assert(
|
||||
ident.type === Syntax.Identifier,
|
||||
"Target should be identifier.",
|
||||
);
|
||||
for (i = 0, iz = this.references.length; i < iz; ++i) {
|
||||
ref = this.references[i];
|
||||
if (ref.identifier === ident) {
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns this scope is static
|
||||
* @function Scope#isStatic
|
||||
* @returns {boolean} static
|
||||
*/
|
||||
isStatic() {
|
||||
return !this.dynamic;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns this scope has materialized arguments
|
||||
* @function Scope#isArgumentsMaterialized
|
||||
* @returns {any} arguments materialized
|
||||
*/ // eslint-disable-next-line class-methods-use-this -- Desired as instance method
|
||||
isArgumentsMaterialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns this scope has materialized `this` reference
|
||||
* @function Scope#isThisMaterialized
|
||||
* @returns {any} this materialized
|
||||
*/ // eslint-disable-next-line class-methods-use-this -- Desired as instance method
|
||||
isThisMaterialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
isUsedName(name) {
|
||||
if (this.set.has(name)) {
|
||||
return true;
|
||||
}
|
||||
for (let i = 0, iz = this.through.length; i < iz; ++i) {
|
||||
if (this.through[i].identifier.name === name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global scope.
|
||||
* @implements {types.GlobalScope}
|
||||
*/
|
||||
class GlobalScope extends Scope {
|
||||
constructor(scopeManager, block) {
|
||||
super(scopeManager, "global", null, block, false);
|
||||
this.implicit = {
|
||||
set: new Map(),
|
||||
|
||||
/** @type {Variable[]} */
|
||||
variables: [],
|
||||
|
||||
/**
|
||||
* List of {@link Reference}s that are left to be resolved (i.e. which
|
||||
* need to be linked to the variable they refer to).
|
||||
* @member {Reference[]} Scope#implicit#left
|
||||
* @type {Reference[]}
|
||||
*/
|
||||
left: [],
|
||||
};
|
||||
}
|
||||
|
||||
__close(scopeManager) {
|
||||
const implicit = [];
|
||||
|
||||
// @ts-ignore -- __left should be an array here
|
||||
for (let i = 0, iz = this.__left.length; i < iz; ++i) {
|
||||
// @ts-ignore -- __left should be an array here
|
||||
const ref = this.__left[i];
|
||||
|
||||
if (
|
||||
ref.__maybeImplicitGlobal &&
|
||||
!this.set.has(ref.identifier.name)
|
||||
) {
|
||||
implicit.push(ref.__maybeImplicitGlobal);
|
||||
}
|
||||
}
|
||||
|
||||
// create an implicit global variable from assignment expression
|
||||
for (let i = 0, iz = implicit.length; i < iz; ++i) {
|
||||
const info = implicit[i];
|
||||
|
||||
this.__defineImplicit(
|
||||
info.pattern,
|
||||
new Definition(
|
||||
Variable.ImplicitGlobalVariable,
|
||||
info.pattern,
|
||||
info.node,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
super.__close(scopeManager);
|
||||
|
||||
this.implicit.left = [...this.through];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
__defineImplicit(node, def) {
|
||||
if (node && node.type === Syntax.Identifier) {
|
||||
this.__defineGeneric(
|
||||
node.name,
|
||||
this.implicit.set,
|
||||
this.implicit.variables,
|
||||
node,
|
||||
def,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
__addVariables(names) {
|
||||
for (const name of names) {
|
||||
this.__defineGeneric(name, this.set, this.variables, null, null);
|
||||
}
|
||||
|
||||
const namesSet = new Set(names);
|
||||
|
||||
this.through = this.through.filter(reference => {
|
||||
const name = reference.identifier.name;
|
||||
|
||||
if (namesSet.has(name)) {
|
||||
const variable = this.set.get(name);
|
||||
|
||||
reference.resolved = variable;
|
||||
variable.references.push(reference);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.implicit.variables = this.implicit.variables.filter(variable => {
|
||||
const name = variable.name;
|
||||
|
||||
if (namesSet.has(name)) {
|
||||
this.implicit.set.delete(name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.implicit.left = this.implicit.left.filter(
|
||||
reference => !namesSet.has(reference.identifier.name),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Module scope.
|
||||
* @implements {types.ModuleScope}
|
||||
*/
|
||||
class ModuleScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "module", upperScope, block, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function expression name scope.
|
||||
* @implements {types.FunctionExpressionNameScope}
|
||||
*/
|
||||
class FunctionExpressionNameScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(
|
||||
scopeManager,
|
||||
"function-expression-name",
|
||||
upperScope,
|
||||
block,
|
||||
false,
|
||||
);
|
||||
this.__define(
|
||||
block.id,
|
||||
new Definition(
|
||||
Variable.FunctionName,
|
||||
block.id,
|
||||
block,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
),
|
||||
);
|
||||
this.functionExpressionScope = /** @type {const} */ (true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Catch scope.
|
||||
* @implements {types.CatchScope}
|
||||
*/
|
||||
class CatchScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "catch", upperScope, block, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* With statement scope.
|
||||
* @implements {types.WithScope}
|
||||
*/
|
||||
class WithScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "with", upperScope, block, false);
|
||||
}
|
||||
|
||||
__close(scopeManager) {
|
||||
if (this.__shouldStaticallyClose(scopeManager)) {
|
||||
return super.__close(scopeManager);
|
||||
}
|
||||
|
||||
// @ts-ignore -- __left should be an array here
|
||||
for (let i = 0, iz = this.__left.length; i < iz; ++i) {
|
||||
// @ts-ignore -- __left should be an array here
|
||||
const ref = this.__left[i];
|
||||
|
||||
ref.tainted = true;
|
||||
this.__delegateToUpperScope(ref);
|
||||
}
|
||||
this.__left = null;
|
||||
|
||||
return this.upper;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Block scope.
|
||||
* @implements {types.BlockScope}
|
||||
*/
|
||||
class BlockScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "block", upperScope, block, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch scope.
|
||||
* @implements {types.SwitchScope}
|
||||
*/
|
||||
class SwitchScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "switch", upperScope, block, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function scope.
|
||||
* @implements {types.FunctionScope}
|
||||
*/
|
||||
class FunctionScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block, isMethodDefinition) {
|
||||
super(scopeManager, "function", upperScope, block, isMethodDefinition);
|
||||
|
||||
// section 9.2.13, FunctionDeclarationInstantiation.
|
||||
// NOTE Arrow functions never have an arguments objects.
|
||||
if (this.block.type !== Syntax.ArrowFunctionExpression) {
|
||||
this.__defineArguments();
|
||||
}
|
||||
}
|
||||
|
||||
isArgumentsMaterialized() {
|
||||
// TODO(Constellation)
|
||||
// We can more aggressive on this condition like this.
|
||||
//
|
||||
// function t() {
|
||||
// // arguments of t is always hidden.
|
||||
// function arguments() {
|
||||
// }
|
||||
// }
|
||||
if (this.block.type === Syntax.ArrowFunctionExpression) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.isStatic()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const variable = this.set.get("arguments");
|
||||
|
||||
assert(variable, "Always have arguments variable.");
|
||||
return variable.tainted || variable.references.length !== 0;
|
||||
}
|
||||
|
||||
isThisMaterialized() {
|
||||
if (!this.isStatic()) {
|
||||
return true;
|
||||
}
|
||||
return this.thisFound;
|
||||
}
|
||||
|
||||
__defineArguments() {
|
||||
this.__defineGeneric("arguments", this.set, this.variables, null, null);
|
||||
this.taints.set("arguments", true);
|
||||
}
|
||||
|
||||
// References in default parameters isn't resolved to variables which are in their function body.
|
||||
// const x = 1
|
||||
// function f(a = x) { // This `x` is resolved to the `x` in the outer scope.
|
||||
// const x = 2
|
||||
// console.log(a)
|
||||
// }
|
||||
__isValidResolution(ref, variable) {
|
||||
// If `options.nodejsScope` is true, `this.block` becomes a Program node.
|
||||
if (this.block.type === "Program") {
|
||||
return true;
|
||||
}
|
||||
|
||||
const bodyStart = this.block.body.range[0];
|
||||
|
||||
// It's invalid resolution in the following case:
|
||||
return !(
|
||||
variable.scope === this &&
|
||||
ref.identifier.range[0] < bodyStart && // the reference is in the parameter part.
|
||||
variable.defs.every(d => d.name.range[0] >= bodyStart) // the variable is in the body.
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope of for, for-in, and for-of statements.
|
||||
* @implements {types.ForScope}
|
||||
*/
|
||||
class ForScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "for", upperScope, block, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class scope.
|
||||
* @implements {types.ClassScope}
|
||||
*/
|
||||
class ClassScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "class", upperScope, block, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class field initializer scope.
|
||||
* @implements {types.ClassFieldInitializerScope}
|
||||
*/
|
||||
class ClassFieldInitializerScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "class-field-initializer", upperScope, block, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class static block scope.
|
||||
* @implements {types.ClassStaticBlockScope}
|
||||
*/
|
||||
class ClassStaticBlockScope extends Scope {
|
||||
constructor(scopeManager, upperScope, block) {
|
||||
super(scopeManager, "class-static-block", upperScope, block, true);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Scope,
|
||||
GlobalScope,
|
||||
ModuleScope,
|
||||
FunctionExpressionNameScope,
|
||||
CatchScope,
|
||||
WithScope,
|
||||
BlockScope,
|
||||
SwitchScope,
|
||||
FunctionScope,
|
||||
ForScope,
|
||||
ClassScope,
|
||||
ClassFieldInitializerScope,
|
||||
ClassStaticBlockScope,
|
||||
};
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
* @fileoverview A rule to set the maximum number of statements in a function.
|
||||
* @author Ian Christian Myers
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const { upperCaseFirst } = require("../shared/string-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Enforce a maximum number of statements allowed in function blocks",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/max-statements",
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
maximum: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
},
|
||||
max: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
ignoreTopLevelFunctions: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
defaultOptions: [10],
|
||||
|
||||
messages: {
|
||||
exceed: "{{name}} has too many statements ({{count}}). Maximum allowed is {{max}}.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
const functionStack = [],
|
||||
option = context.options[0],
|
||||
ignoreTopLevelFunctions =
|
||||
(context.options[1] &&
|
||||
context.options[1].ignoreTopLevelFunctions) ||
|
||||
false,
|
||||
topLevelFunctions = [];
|
||||
let maxStatements = 10;
|
||||
|
||||
if (
|
||||
typeof option === "object" &&
|
||||
(Object.hasOwn(option, "maximum") || Object.hasOwn(option, "max"))
|
||||
) {
|
||||
maxStatements = option.maximum || option.max;
|
||||
} else if (typeof option === "number") {
|
||||
maxStatements = option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a node if it has too many statements
|
||||
* @param {ASTNode} node node to evaluate
|
||||
* @param {number} count Number of statements in node
|
||||
* @param {number} max Maximum number of statements allowed
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function reportIfTooManyStatements(node, count, max) {
|
||||
if (count > max) {
|
||||
const name = upperCaseFirst(
|
||||
astUtils.getFunctionNameWithKind(node),
|
||||
);
|
||||
|
||||
context.report({
|
||||
node,
|
||||
loc: astUtils.getFunctionHeadLoc(node, context.sourceCode),
|
||||
messageId: "exceed",
|
||||
data: { name, count, max },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When parsing a new function, store it in our function stack
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function startFunction() {
|
||||
functionStack.push(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the node at the end of function
|
||||
* @param {ASTNode} node node to evaluate
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function endFunction(node) {
|
||||
const count = functionStack.pop();
|
||||
|
||||
/*
|
||||
* This rule does not apply to class static blocks, but we have to track them so
|
||||
* that statements in them do not count as statements in the enclosing function.
|
||||
*/
|
||||
if (node.type === "StaticBlock") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ignoreTopLevelFunctions && functionStack.length === 0) {
|
||||
topLevelFunctions.push({ node, count });
|
||||
} else {
|
||||
reportIfTooManyStatements(node, count, maxStatements);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the count of the functions
|
||||
* @param {ASTNode} node node to evaluate
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function countStatements(node) {
|
||||
functionStack[functionStack.length - 1] += node.body.length;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public API
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
FunctionDeclaration: startFunction,
|
||||
FunctionExpression: startFunction,
|
||||
ArrowFunctionExpression: startFunction,
|
||||
StaticBlock: startFunction,
|
||||
|
||||
BlockStatement: countStatements,
|
||||
|
||||
"FunctionDeclaration:exit": endFunction,
|
||||
"FunctionExpression:exit": endFunction,
|
||||
"ArrowFunctionExpression:exit": endFunction,
|
||||
"StaticBlock:exit": endFunction,
|
||||
|
||||
"Program:exit"() {
|
||||
if (topLevelFunctions.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
topLevelFunctions.forEach(element => {
|
||||
const count = element.count;
|
||||
const node = element.node;
|
||||
|
||||
reportIfTooManyStatements(node, count, maxStatements);
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.rangeToLoc = rangeToLoc;
|
||||
function rangeToLoc(sourceCode, range) {
|
||||
return {
|
||||
end: sourceCode.getLocFromIndex(range[1]),
|
||||
start: sourceCode.getLocFromIndex(range[0]),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,771 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const empty = z.templateLiteral([]);
|
||||
const hello = z.templateLiteral(["hello"]);
|
||||
const world = z.templateLiteral(["", z.literal("world")]);
|
||||
const one = z.templateLiteral([1]);
|
||||
const two = z.templateLiteral(["", z.literal(2)]);
|
||||
const onePointOne = z.templateLiteral([z.literal(1.1)]);
|
||||
const truee = z.templateLiteral([true]);
|
||||
const anotherTrue = z.templateLiteral(["", z.literal(true)]);
|
||||
const falsee = z.templateLiteral([false]);
|
||||
const anotherFalse = z.templateLiteral(["", z.literal(false)]);
|
||||
const nulll = z.templateLiteral([null]);
|
||||
const anotherNull = z.templateLiteral(["", z.null()]);
|
||||
const undefinedd = z.templateLiteral([undefined]);
|
||||
const anotherUndefined = z.templateLiteral(["", z.undefined()]);
|
||||
const anyString = z.templateLiteral(["", z.string()]);
|
||||
const lazyString = z.templateLiteral(["", z.lazy(() => z.string())]);
|
||||
const anyNumber = z.templateLiteral(["", z.number()]);
|
||||
const anyInt = z.templateLiteral(["", z.number().int()]);
|
||||
// const anyFiniteNumber = z.templateLiteral(["", z.number().finite()]);
|
||||
// const anyNegativeNumber = z.templateLiteral(["", z.number().negative()]);
|
||||
// const anyPositiveNumber = z.templateLiteral(["", z.number().positive()]);
|
||||
// const zeroButInADumbWay = z.templateLiteral(["", z.number().nonnegative().nonpositive()]);
|
||||
// const finiteButInADumbWay = z.templateLiteral(["", z.number().min(5).max(10)]);
|
||||
const bool = z.templateLiteral(["", z.boolean()]);
|
||||
const bigone = z.templateLiteral(["", z.literal(BigInt(1))]);
|
||||
const anyBigint = z.templateLiteral(["", z.bigint()]);
|
||||
const nullableYo = z.templateLiteral(["", z.nullable(z.literal("yo"))]);
|
||||
const nullableString = z.templateLiteral(["", z.nullable(z.string())]);
|
||||
const optionalYeah = z.templateLiteral(["", z.literal("yeah").optional()]);
|
||||
|
||||
const optionalString = z.templateLiteral(["", z.string().optional()]);
|
||||
const optionalNumber = z.templateLiteral(["", z.number().optional()]);
|
||||
const nullishBruh = z.templateLiteral(["", z.literal("bruh").nullish()]);
|
||||
const nullishString = z.templateLiteral(["", z.string().nullish()]);
|
||||
const cuid = z.templateLiteral(["", z.string().cuid()]);
|
||||
const cuidZZZ = z.templateLiteral(["", z.string().cuid(), "ZZZ"]);
|
||||
const cuid2 = z.templateLiteral(["", z.string().cuid2()]);
|
||||
const datetime = z.templateLiteral(["", z.string().datetime()]);
|
||||
const email = z.templateLiteral(["", z.string().email()]);
|
||||
// const ip = z.templateLiteral(["", z.string().ip()]);
|
||||
const ipv4 = z.templateLiteral(["", z.string().ipv4()]);
|
||||
const ipv6 = z.templateLiteral(["", z.string().ipv6()]);
|
||||
const mac = z.templateLiteral(["", z.mac()]);
|
||||
const ulid = z.templateLiteral(["", z.string().ulid()]);
|
||||
const uuid = z.templateLiteral(["", z.string().uuid()]);
|
||||
const stringAToZ = z.templateLiteral(["", z.string().regex(/^[a-z]+$/)]);
|
||||
const stringStartsWith = z.templateLiteral(["", z.string().startsWith("hello")]);
|
||||
const stringEndsWith = z.templateLiteral(["", z.string().endsWith("world")]);
|
||||
const stringMax5 = z.templateLiteral(["", z.string().max(5)]);
|
||||
const stringMin5 = z.templateLiteral(["", z.string().min(5)]);
|
||||
const stringLen5 = z.templateLiteral(["", z.string().length(5)]);
|
||||
const stringMin5Max10 = z.templateLiteral(["", z.string().min(5).max(10)]);
|
||||
const stringStartsWithMax5 = z.templateLiteral(["", z.string().startsWith("hello").max(5)]);
|
||||
const brandedString = z.templateLiteral(["", z.string().min(1).brand("myBrand")]);
|
||||
// const anything = z.templateLiteral(["", z.any()]);
|
||||
|
||||
const url = z.templateLiteral(["https://", z.string().regex(/\w+/), ".", z.enum(["com", "net"])]);
|
||||
|
||||
const measurement = z.templateLiteral([
|
||||
"",
|
||||
z.number().finite(),
|
||||
z.enum(["px", "em", "rem", "vh", "vw", "vmin", "vmax"]).optional(),
|
||||
]);
|
||||
|
||||
const connectionString = z.templateLiteral([
|
||||
"mongodb://",
|
||||
z
|
||||
.templateLiteral([
|
||||
"",
|
||||
z.string().regex(/\w+/).describe("username"),
|
||||
":",
|
||||
z.string().regex(/\w+/).describe("password"),
|
||||
"@",
|
||||
])
|
||||
.optional(),
|
||||
z.string().regex(/\w+/).describe("host"),
|
||||
":",
|
||||
z.number().finite().int().positive().describe("port"),
|
||||
z
|
||||
.templateLiteral([
|
||||
"/",
|
||||
z.string().regex(/\w+/).optional().describe("defaultauthdb"),
|
||||
z
|
||||
.templateLiteral([
|
||||
"?",
|
||||
z
|
||||
.string()
|
||||
.regex(/^\w+=\w+(&\w+=\w+)*$/)
|
||||
.optional()
|
||||
.describe("options"),
|
||||
])
|
||||
.optional(),
|
||||
])
|
||||
.optional(),
|
||||
]);
|
||||
|
||||
test("template literal type inference", () => {
|
||||
expectTypeOf<z.infer<typeof empty>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof hello>>().toEqualTypeOf<`hello`>();
|
||||
expectTypeOf<z.infer<typeof world>>().toEqualTypeOf<`world`>();
|
||||
expectTypeOf<z.infer<typeof one>>().toEqualTypeOf<`1`>();
|
||||
expectTypeOf<z.infer<typeof two>>().toEqualTypeOf<`2`>();
|
||||
expectTypeOf<z.infer<typeof truee>>().toEqualTypeOf<`true`>();
|
||||
expectTypeOf<z.infer<typeof anotherTrue>>().toEqualTypeOf<`true`>();
|
||||
expectTypeOf<z.infer<typeof falsee>>().toEqualTypeOf<`false`>();
|
||||
expectTypeOf<z.infer<typeof anotherFalse>>().toEqualTypeOf<`false`>();
|
||||
expectTypeOf<z.infer<typeof nulll>>().toEqualTypeOf<`null`>();
|
||||
expectTypeOf<z.infer<typeof anotherNull>>().toEqualTypeOf<`null`>();
|
||||
expectTypeOf<z.infer<typeof undefinedd>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof anotherUndefined>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof anyString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof lazyString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof anyNumber>>().toEqualTypeOf<`${number}`>();
|
||||
expectTypeOf<z.infer<typeof anyInt>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyFiniteNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyNegativeNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyPositiveNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof zeroButInADumbWay>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof finiteButInADumbWay>>().toEqualTypeOf<`${number}`>();
|
||||
expectTypeOf<z.infer<typeof bool>>().toEqualTypeOf<`true` | `false`>();
|
||||
expectTypeOf<z.infer<typeof bigone>>().toEqualTypeOf<`${bigint}`>();
|
||||
expectTypeOf<z.infer<typeof anyBigint>>().toEqualTypeOf<`${bigint}`>();
|
||||
expectTypeOf<z.infer<typeof nullableYo>>().toEqualTypeOf<`yo` | `null`>();
|
||||
expectTypeOf<z.infer<typeof nullableString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof optionalYeah>>().toEqualTypeOf<`yeah` | ``>();
|
||||
expectTypeOf<z.infer<typeof optionalString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof optionalNumber>>().toEqualTypeOf<`${number}` | ``>();
|
||||
expectTypeOf<z.infer<typeof nullishBruh>>().toEqualTypeOf<`bruh` | `null` | ``>();
|
||||
expectTypeOf<z.infer<typeof nullishString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof cuid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof cuidZZZ>>().toEqualTypeOf<`${string}ZZZ`>();
|
||||
expectTypeOf<z.infer<typeof cuid2>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof datetime>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof email>>().toEqualTypeOf<string>();
|
||||
// expectTypeOf<z.infer<typeof ip>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ipv4>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ipv6>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof mac>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ulid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof uuid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringAToZ>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringStartsWith>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringEndsWith>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMax5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMin5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringLen5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMin5Max10>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringStartsWithMax5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof brandedString>>().toEqualTypeOf<`${string & z.core.$brand<"myBrand">}`>();
|
||||
|
||||
// expectTypeOf<z.infer<typeof anything>>().toEqualTypeOf<`${any}`>();
|
||||
|
||||
expectTypeOf<z.infer<typeof url>>().toEqualTypeOf<`https://${string}.com` | `https://${string}.net`>();
|
||||
|
||||
expectTypeOf<z.infer<typeof measurement>>().toEqualTypeOf<
|
||||
| `${number}`
|
||||
| `${number}px`
|
||||
| `${number}em`
|
||||
| `${number}rem`
|
||||
| `${number}vh`
|
||||
| `${number}vw`
|
||||
| `${number}vmin`
|
||||
| `${number}vmax`
|
||||
>();
|
||||
|
||||
expectTypeOf<z.infer<typeof connectionString>>().toEqualTypeOf<
|
||||
| `mongodb://${string}:${number}`
|
||||
| `mongodb://${string}:${number}/${string}`
|
||||
| `mongodb://${string}:${number}/${string}?${string}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}/${string}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}/${string}?${string}`
|
||||
>();
|
||||
});
|
||||
|
||||
test("template literal unsupported args", () => {
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.object({})])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.array(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.union([z.object({}), z.string()])])
|
||||
).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.templateLiteral([z.date()])).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.custom<object>((_) => true)])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
z.templateLiteral([
|
||||
// @ts-expect-error
|
||||
z.discriminatedUnion("discriminator", [z.object({}), z.object({})]),
|
||||
])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.function()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.instanceof(class MyClass {})])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.intersection(z.object({}), z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.map(z.string(), z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.nullable(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.optional(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.promise()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.record(z.unknown())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.set(z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.symbol()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.tuple([z.string()])])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.unknown()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.void()])
|
||||
).toThrow();
|
||||
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.never()])
|
||||
).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.templateLiteral([z.nan()])).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.pipe(z.string(), z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.preprocess(() => true, z.boolean())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.object({}).brand("brand")])
|
||||
).toThrow();
|
||||
|
||||
// these constraints aren't enforced but they shouldn't throw
|
||||
z.templateLiteral([z.number().multipleOf(2)]);
|
||||
z.templateLiteral([z.string().emoji()]);
|
||||
z.templateLiteral([z.string().url()]);
|
||||
z.templateLiteral([z.string().url()]);
|
||||
z.templateLiteral([z.string().trim()]);
|
||||
z.templateLiteral([z.string().includes("train")]);
|
||||
z.templateLiteral([z.string().toLowerCase()]);
|
||||
z.templateLiteral([z.string().toUpperCase()]);
|
||||
});
|
||||
|
||||
test("template literal parsing - success - basic cases", () => {
|
||||
expect(() => z.templateLiteral([]).parse(7)).toThrow();
|
||||
|
||||
empty.parse("");
|
||||
hello.parse("hello");
|
||||
world.parse("world");
|
||||
one.parse("1");
|
||||
two.parse("2");
|
||||
onePointOne.parse("1.1");
|
||||
truee.parse("true");
|
||||
anotherTrue.parse("true");
|
||||
falsee.parse("false");
|
||||
anotherFalse.parse("false");
|
||||
nulll.parse("null");
|
||||
anotherNull.parse("null");
|
||||
undefinedd.parse("undefined");
|
||||
anotherUndefined.parse("undefined");
|
||||
anyString.parse("blahblahblah");
|
||||
anyString.parse("");
|
||||
lazyString.parse("blahblahblah");
|
||||
lazyString.parse("");
|
||||
anyNumber.parse("123");
|
||||
anyNumber.parse("1.23");
|
||||
anyNumber.parse("0");
|
||||
anyNumber.parse("-1.23");
|
||||
anyNumber.parse("-123");
|
||||
// anyNumber.parse("Infinity");
|
||||
// anyNumber.parse("-Infinity");
|
||||
anyInt.parse("123");
|
||||
// anyInt.parse("-123");
|
||||
// anyFiniteNumber.parse("123");
|
||||
// anyFiniteNumber.parse("1.23");
|
||||
// anyFiniteNumber.parse("0");
|
||||
// anyFiniteNumber.parse("-1.23");
|
||||
// anyFiniteNumber.parse("-123");
|
||||
// anyNegativeNumber.parse("-123");
|
||||
// anyNegativeNumber.parse("-1.23");
|
||||
// anyNegativeNumber.parse("-Infinity");
|
||||
// anyPositiveNumber.parse("123");
|
||||
// anyPositiveNumber.parse("1.23");
|
||||
// anyPositiveNumber.parse("Infinity");
|
||||
// zeroButInADumbWay.parse("0");
|
||||
// zeroButInADumbWay.parse("00000");
|
||||
// finiteButInADumbWay.parse("5");
|
||||
// finiteButInADumbWay.parse("10");
|
||||
// finiteButInADumbWay.parse("6.66");
|
||||
bool.parse("true");
|
||||
bool.parse("false");
|
||||
bigone.parse("1");
|
||||
anyBigint.parse("123456");
|
||||
anyBigint.parse("0");
|
||||
// anyBigint.parse("-123456");
|
||||
nullableYo.parse("yo");
|
||||
nullableYo.parse("null");
|
||||
nullableString.parse("abc");
|
||||
nullableString.parse("null");
|
||||
optionalYeah.parse("yeah");
|
||||
optionalYeah.parse("");
|
||||
optionalString.parse("abc");
|
||||
optionalString.parse("");
|
||||
optionalNumber.parse("123");
|
||||
optionalNumber.parse("1.23");
|
||||
optionalNumber.parse("0");
|
||||
optionalNumber.parse("-1.23");
|
||||
optionalNumber.parse("-123");
|
||||
// optionalNumber.parse("Infinity");
|
||||
// optionalNumber.parse("-Infinity");
|
||||
nullishBruh.parse("bruh");
|
||||
nullishBruh.parse("null");
|
||||
nullishBruh.parse("");
|
||||
cuid.parse("cjld2cyuq0000t3rmniod1foy");
|
||||
cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZZ");
|
||||
cuid2.parse("tz4a98xxat96iws9zmbrgj3a");
|
||||
datetime.parse(new Date().toISOString());
|
||||
email.parse("info@example.com");
|
||||
// ip.parse("213.174.246.205");
|
||||
// ip.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452");
|
||||
ipv4.parse("213.174.246.205");
|
||||
ipv6.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452");
|
||||
mac.parse("00:1A:2B:3C:4D:5E");
|
||||
ulid.parse("01GW3D2QZJBYB6P1Z1AE997VPW");
|
||||
uuid.parse("808989fd-3a6e-4af2-b607-737323a176f6");
|
||||
stringAToZ.parse("asudgaskhdgashd");
|
||||
stringStartsWith.parse("hello world");
|
||||
stringEndsWith.parse("hello world");
|
||||
stringMax5.parse("hello");
|
||||
stringMin5.parse("hello");
|
||||
stringLen5.parse("hello");
|
||||
stringMin5Max10.parse("hello worl");
|
||||
stringStartsWithMax5.parse("hello");
|
||||
brandedString.parse("branded string");
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - basic cases", () => {
|
||||
expect(() => empty.parse("a")).toThrow();
|
||||
expect(() => hello.parse("hello!")).toThrow();
|
||||
expect(() => hello.parse("!hello")).toThrow();
|
||||
expect(() => world.parse("world!")).toThrow();
|
||||
expect(() => world.parse("!world")).toThrow();
|
||||
expect(() => one.parse("2")).toThrow();
|
||||
expect(() => one.parse("12")).toThrow();
|
||||
expect(() => one.parse("21")).toThrow();
|
||||
expect(() => onePointOne.parse("1s1")).toThrow();
|
||||
expect(() => two.parse("1")).toThrow();
|
||||
expect(() => two.parse("21")).toThrow();
|
||||
expect(() => two.parse("12")).toThrow();
|
||||
expect(() => truee.parse("false")).toThrow();
|
||||
expect(() => truee.parse("1true")).toThrow();
|
||||
expect(() => truee.parse("true1")).toThrow();
|
||||
expect(() => anotherTrue.parse("false")).toThrow();
|
||||
expect(() => anotherTrue.parse("1true")).toThrow();
|
||||
expect(() => anotherTrue.parse("true1")).toThrow();
|
||||
expect(() => falsee.parse("true")).toThrow();
|
||||
expect(() => falsee.parse("1false")).toThrow();
|
||||
expect(() => falsee.parse("false1")).toThrow();
|
||||
expect(() => anotherFalse.parse("true")).toThrow();
|
||||
expect(() => anotherFalse.parse("1false")).toThrow();
|
||||
expect(() => anotherFalse.parse("false1")).toThrow();
|
||||
expect(() => nulll.parse("123")).toThrow();
|
||||
expect(() => nulll.parse("null1")).toThrow();
|
||||
expect(() => nulll.parse("1null")).toThrow();
|
||||
expect(() => anotherNull.parse("123")).toThrow();
|
||||
expect(() => anotherNull.parse("null1")).toThrow();
|
||||
expect(() => anotherNull.parse("1null")).toThrow();
|
||||
expect(() => undefinedd.parse("123")).toThrow();
|
||||
expect(() => undefinedd.parse("undefined1")).toThrow();
|
||||
expect(() => undefinedd.parse("1undefined")).toThrow();
|
||||
expect(() => anotherUndefined.parse("123")).toThrow();
|
||||
expect(() => anotherUndefined.parse("undefined1")).toThrow();
|
||||
expect(() => anotherUndefined.parse("1undefined")).toThrow();
|
||||
expect(() => anyNumber.parse("2a")).toThrow();
|
||||
expect(() => anyNumber.parse("a2")).toThrow();
|
||||
expect(() => anyNumber.parse("-2a")).toThrow();
|
||||
expect(() => anyNumber.parse("a-2")).toThrow();
|
||||
expect(() => anyNumber.parse("2.5a")).toThrow();
|
||||
expect(() => anyNumber.parse("a2.5")).toThrow();
|
||||
expect(() => anyNumber.parse("Infinitya")).toThrow();
|
||||
expect(() => anyNumber.parse("aInfinity")).toThrow();
|
||||
expect(() => anyNumber.parse("-Infinitya")).toThrow();
|
||||
expect(() => anyNumber.parse("a-Infinity")).toThrow();
|
||||
expect(() => anyNumber.parse("2e5")).toThrow();
|
||||
expect(() => anyNumber.parse("2e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("2e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-Infinity")).toThrow();
|
||||
expect(() => anyNumber.parse("Infinity")).toThrow();
|
||||
expect(() => anyInt.parse("1.23")).toThrow();
|
||||
expect(() => anyInt.parse("-1.23")).toThrow();
|
||||
expect(() => anyInt.parse("d1")).toThrow();
|
||||
expect(() => anyInt.parse("1d")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("Infinity")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("-Infinity")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("123a")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("a123")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("0")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("1")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("Infinity")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("0")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("-1")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("-Infinity")).toThrow();
|
||||
// expect(() => zeroButInADumbWay.parse("1")).toThrow();
|
||||
// expect(() => zeroButInADumbWay.parse("-1")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("Infinity")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("-Infinity")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("-5")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("10a")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("a10")).toThrow();
|
||||
expect(() => bool.parse("123")).toThrow();
|
||||
expect(() => bigone.parse("2")).toThrow();
|
||||
expect(() => bigone.parse("c1")).toThrow();
|
||||
expect(() => anyBigint.parse("1.23")).toThrow();
|
||||
expect(() => anyBigint.parse("-1.23")).toThrow();
|
||||
expect(() => anyBigint.parse("c123")).toThrow();
|
||||
expect(() => nullableYo.parse("yo1")).toThrow();
|
||||
expect(() => nullableYo.parse("1yo")).toThrow();
|
||||
expect(() => nullableYo.parse("null1")).toThrow();
|
||||
expect(() => nullableYo.parse("1null")).toThrow();
|
||||
expect(() => optionalYeah.parse("yeah1")).toThrow();
|
||||
expect(() => optionalYeah.parse("1yeah")).toThrow();
|
||||
expect(() => optionalYeah.parse("undefined")).toThrow();
|
||||
expect(() => optionalNumber.parse("123a")).toThrow();
|
||||
expect(() => optionalNumber.parse("a123")).toThrow();
|
||||
// expect(() => optionalNumber.parse("Infinitya")).toThrow();
|
||||
// expect(() => optionalNumber.parse("aInfinity")).toThrow();
|
||||
expect(() => nullishBruh.parse("bruh1")).toThrow();
|
||||
expect(() => nullishBruh.parse("1bruh")).toThrow();
|
||||
expect(() => nullishBruh.parse("null1")).toThrow();
|
||||
expect(() => nullishBruh.parse("1null")).toThrow();
|
||||
expect(() => nullishBruh.parse("undefined")).toThrow();
|
||||
expect(() => cuid.parse("bjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuid.parse("cjld2")).toThrow();
|
||||
expect(() => cuid.parse("cjld2 cyu")).toThrow();
|
||||
expect(() => cuid.parse("cjld2cyuq0000t3rmniod1foy ")).toThrow();
|
||||
expect(() => cuid.parse("1cjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZY")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZZ1")).toThrow();
|
||||
expect(() => cuidZZZ.parse("1cjld2cyuq0000t3rmniod1foyZZZ")).toThrow();
|
||||
expect(() => cuid2.parse("A9z4a98xxat96iws9zmbrgj3a")).toThrow();
|
||||
expect(() => cuid2.parse("tz4a98xxat96iws9zmbrgj3!")).toThrow();
|
||||
expect(() => datetime.parse("2022-01-01 00:00:00")).toThrow();
|
||||
expect(() => email.parse("info@example.com@")).toThrow();
|
||||
// expect(() => ip.parse("213.174.246:205")).toThrow();
|
||||
// expect(() => ip.parse("c359.f57c:21e5:39eb:1187:e501:f936:b452")).toThrow();
|
||||
expect(() => ipv4.parse("1213.174.246.205")).toThrow();
|
||||
expect(() => ipv4.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452")).toThrow();
|
||||
expect(() => ipv6.parse("c359:f57c:21e5:39eb:1187:e501:f936:b4521")).toThrow();
|
||||
expect(() => ipv6.parse("213.174.246.205")).toThrow();
|
||||
expect(() => mac.parse("00:1A:2B:3C:4D:5E:6A:7B")).toThrow();
|
||||
expect(() => mac.parse("00:1A:2B:3C")).toThrow();
|
||||
expect(() => ulid.parse("01GW3D2QZJBYB6P1Z1AE997VPW!")).toThrow();
|
||||
expect(() => uuid.parse("808989fd-3a6e-4af2-b607-737323a176f6Z")).toThrow();
|
||||
expect(() => uuid.parse("Z808989fd-3a6e-4af2-b607-737323a176f6")).toThrow();
|
||||
expect(() => stringAToZ.parse("asdasdasd1")).toThrow();
|
||||
expect(() => stringAToZ.parse("1asdasdasd")).toThrow();
|
||||
expect(() => stringStartsWith.parse("ahello")).toThrow();
|
||||
expect(() => stringEndsWith.parse("worlda")).toThrow();
|
||||
expect(() => stringMax5.parse("123456")).toThrow();
|
||||
expect(() => stringMin5.parse("1234")).toThrow();
|
||||
expect(() => stringLen5.parse("123456")).toThrow();
|
||||
expect(() => stringLen5.parse("1234")).toThrow();
|
||||
expect(() => stringMin5Max10.parse("1234")).toThrow();
|
||||
expect(() => stringMin5Max10.parse("12345678901")).toThrow();
|
||||
|
||||
// the "startswith" overrides the max length
|
||||
// expect(() => stringStartsWithMax5.parse("hello1")).toThrow();
|
||||
expect(() => stringStartsWithMax5.parse("1hell")).toThrow();
|
||||
expect(() => brandedString.parse("")).toThrow();
|
||||
});
|
||||
|
||||
test("regexes", () => {
|
||||
expect(empty._zod.pattern.source).toMatchInlineSnapshot(`"^$"`);
|
||||
expect(hello._zod.pattern.source).toMatchInlineSnapshot(`"^hello$"`);
|
||||
expect(world._zod.pattern.source).toMatchInlineSnapshot(`"^(world)$"`);
|
||||
expect(one._zod.pattern.source).toMatchInlineSnapshot(`"^1$"`);
|
||||
expect(two._zod.pattern.source).toMatchInlineSnapshot(`"^(2)$"`);
|
||||
expect(truee._zod.pattern.source).toMatchInlineSnapshot(`"^true$"`);
|
||||
expect(anotherTrue._zod.pattern.source).toMatchInlineSnapshot(`"^(true)$"`);
|
||||
expect(falsee._zod.pattern.source).toMatchInlineSnapshot(`"^false$"`);
|
||||
expect(anotherFalse._zod.pattern.source).toMatchInlineSnapshot(`"^(false)$"`);
|
||||
expect(nulll._zod.pattern.source).toMatchInlineSnapshot(`"^null$"`);
|
||||
expect(anotherNull._zod.pattern.source).toMatchInlineSnapshot(`"^null$"`);
|
||||
expect(undefinedd._zod.pattern.source).toMatchInlineSnapshot(`"^undefined$"`);
|
||||
expect(anotherUndefined._zod.pattern.source).toMatchInlineSnapshot(`"^undefined$"`);
|
||||
expect(anyString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,}$"`);
|
||||
expect(lazyString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,}$"`);
|
||||
expect(anyNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
expect(anyInt._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+$"`);
|
||||
// expect(anyFiniteNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(anyNegativeNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(anyPositiveNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(zeroButInADumbWay._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(finiteButInADumbWay._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
expect(bool._zod.pattern.source).toMatchInlineSnapshot(`"^(?:true|false)$"`);
|
||||
expect(bigone._zod.pattern.source).toMatchInlineSnapshot(`"^(1)$"`);
|
||||
expect(anyBigint._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+n?$"`);
|
||||
expect(nullableYo._zod.pattern.source).toMatchInlineSnapshot(`"^((yo)|null)$"`);
|
||||
expect(nullableString._zod.pattern.source).toMatchInlineSnapshot(`"^([\\s\\S]{0,}|null)$"`);
|
||||
expect(optionalYeah._zod.pattern.source).toMatchInlineSnapshot(`"^((yeah))?$"`);
|
||||
expect(optionalString._zod.pattern.source).toMatchInlineSnapshot(`"^([\\s\\S]{0,})?$"`);
|
||||
expect(optionalNumber._zod.pattern.source).toMatchInlineSnapshot(`"^(-?\\d+(?:\\.\\d+)?)?$"`);
|
||||
expect(nullishBruh._zod.pattern.source).toMatchInlineSnapshot(`"^(((bruh)|null))?$"`);
|
||||
expect(nullishString._zod.pattern.source).toMatchInlineSnapshot(`"^(([\\s\\S]{0,}|null))?$"`);
|
||||
expect(cuid._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][0-9a-z]{6,}$"`);
|
||||
expect(cuidZZZ._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][0-9a-z]{6,}ZZZ$"`);
|
||||
expect(cuid2._zod.pattern.source).toMatchInlineSnapshot(`"^[0-9a-z]+$"`);
|
||||
expect(datetime._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"`
|
||||
);
|
||||
expect(email._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"`
|
||||
);
|
||||
// expect(ip._zod.pattern.source).toMatchInlineSnapshot(
|
||||
// `"^(^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$)|(^(([a-fA-F0-9]{1,4}:){7}|::([a-fA-F0-9]{1,4}:){0,6}|([a-fA-F0-9]{1,4}:){1}:([a-fA-F0-9]{1,4}:){0,5}|([a-fA-F0-9]{1,4}:){2}:([a-fA-F0-9]{1,4}:){0,4}|([a-fA-F0-9]{1,4}:){3}:([a-fA-F0-9]{1,4}:){0,3}|([a-fA-F0-9]{1,4}:){4}:([a-fA-F0-9]{1,4}:){0,2}|([a-fA-F0-9]{1,4}:){5}:([a-fA-F0-9]{1,4}:){0,1})([a-fA-F0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$)$"`
|
||||
// );
|
||||
expect(ipv4._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"`
|
||||
);
|
||||
expect(ipv6._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$"`
|
||||
);
|
||||
expect(mac._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$"`
|
||||
);
|
||||
expect(ulid._zod.pattern.source).toMatchInlineSnapshot(`"^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$"`);
|
||||
expect(uuid._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"`
|
||||
);
|
||||
expect(stringAToZ._zod.pattern.source).toMatchInlineSnapshot(`"^[a-z]+$"`);
|
||||
expect(stringStartsWith._zod.pattern.source).toMatchInlineSnapshot(`"^hello.*$"`);
|
||||
expect(stringEndsWith._zod.pattern.source).toMatchInlineSnapshot(`"^.*world$"`);
|
||||
expect(stringMax5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,5}$"`);
|
||||
expect(stringMin5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,}$"`);
|
||||
expect(stringLen5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,5}$"`);
|
||||
expect(stringMin5Max10._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,10}$"`);
|
||||
expect(brandedString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{1,}$"`);
|
||||
expect(url._zod.pattern.source).toMatchInlineSnapshot(`"^https:\\/\\/\\w+\\.(com|net)$"`);
|
||||
expect(measurement._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?((px|em|rem|vh|vw|vmin|vmax))?$"`);
|
||||
expect(connectionString._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^mongodb:\\/\\/(\\w+:\\w+@)?\\w+:-?\\d+(\\/(\\w+)?(\\?(\\w+=\\w+(&\\w+=\\w+)*)?)?)?$"`
|
||||
);
|
||||
});
|
||||
|
||||
test("template literal parsing - success - complex cases", () => {
|
||||
url.parse("https://example.com");
|
||||
url.parse("https://speedtest.net");
|
||||
|
||||
// measurement.parse(1);
|
||||
// measurement.parse(1.1);
|
||||
// measurement.parse(0);
|
||||
// measurement.parse(-1.1);
|
||||
// measurement.parse(-1);
|
||||
measurement.parse("1");
|
||||
measurement.parse("1.1");
|
||||
measurement.parse("0");
|
||||
measurement.parse("-1");
|
||||
measurement.parse("-1.1");
|
||||
measurement.parse("1px");
|
||||
measurement.parse("1.1px");
|
||||
measurement.parse("0px");
|
||||
measurement.parse("-1px");
|
||||
measurement.parse("-1.1px");
|
||||
measurement.parse("1em");
|
||||
measurement.parse("1.1em");
|
||||
measurement.parse("0em");
|
||||
measurement.parse("-1em");
|
||||
measurement.parse("-1.1em");
|
||||
measurement.parse("1rem");
|
||||
measurement.parse("1.1rem");
|
||||
measurement.parse("0rem");
|
||||
measurement.parse("-1rem");
|
||||
measurement.parse("-1.1rem");
|
||||
measurement.parse("1vh");
|
||||
measurement.parse("1.1vh");
|
||||
measurement.parse("0vh");
|
||||
measurement.parse("-1vh");
|
||||
measurement.parse("-1.1vh");
|
||||
measurement.parse("1vw");
|
||||
measurement.parse("1.1vw");
|
||||
measurement.parse("0vw");
|
||||
measurement.parse("-1vw");
|
||||
measurement.parse("-1.1vw");
|
||||
measurement.parse("1vmin");
|
||||
measurement.parse("1.1vmin");
|
||||
measurement.parse("0vmin");
|
||||
measurement.parse("-1vmin");
|
||||
measurement.parse("-1.1vmin");
|
||||
measurement.parse("1vmax");
|
||||
measurement.parse("1.1vmax");
|
||||
measurement.parse("0vmax");
|
||||
measurement.parse("-1vmax");
|
||||
measurement.parse("-1.1vmax");
|
||||
|
||||
connectionString.parse("mongodb://host:1234");
|
||||
connectionString.parse("mongodb://host:1234/");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb?authSource=admin");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb?authSource=admin&connectTimeoutMS=300000");
|
||||
connectionString.parse("mongodb://host:1234/?authSource=admin");
|
||||
connectionString.parse("mongodb://host:1234/?authSource=admin&connectTimeoutMS=300000");
|
||||
connectionString.parse("mongodb://username:password@host:1234");
|
||||
connectionString.parse("mongodb://username:password@host:1234/");
|
||||
connectionString.parse("mongodb://username:password@host:1234/defaultauthdb");
|
||||
connectionString.parse("mongodb://username:password@host:1234/defaultauthdb?authSource=admin");
|
||||
connectionString.parse(
|
||||
"mongodb://username:password@host:1234/defaultauthdb?authSource=admin&connectTimeoutMS=300000"
|
||||
);
|
||||
connectionString.parse("mongodb://username:password@host:1234/?authSource=admin");
|
||||
connectionString.parse("mongodb://username:password@host:1234/?authSource=admin&connectTimeoutMS=300000");
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - complex cases", () => {
|
||||
expect(() => url.parse("http://example.com")).toThrow();
|
||||
expect(() => url.parse("https://.com")).toThrow();
|
||||
expect(() => url.parse("https://examplecom")).toThrow();
|
||||
expect(() => url.parse("https://example.org")).toThrow();
|
||||
expect(() => url.parse("https://example.net.il")).toThrow();
|
||||
|
||||
expect(() => measurement.parse("1.1.1")).toThrow();
|
||||
expect(() => measurement.parse("Infinity")).toThrow();
|
||||
expect(() => measurement.parse("-Infinity")).toThrow();
|
||||
expect(() => measurement.parse("NaN")).toThrow();
|
||||
expect(() => measurement.parse("1%")).toThrow();
|
||||
|
||||
expect(() => connectionString.parse("mongod://host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:d234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:12.34")).toThrow();
|
||||
// Note: template literal regex currently allows negative numbers despite .positive() constraint
|
||||
// This is a known limitation where template literals use regex patterns directly
|
||||
// expect(() => connectionString.parse("mongodb://host:-1234")).toThrow();
|
||||
// expect(() => connectionString.parse("mongodb://host:-12.34")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://:password@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://usernamepassword@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://username:@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/defaultauthdb?authSourceadmin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/?authSourceadmin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/defaultauthdb?&authSource=admin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/?&authSource=admin")).toThrow();
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - issue format", () => {
|
||||
expect(anotherNull.safeParse("1null")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^null$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(cuidZZZ.safeParse("1cjld2cyuq0000t3rmniod1foyZZZ")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^[cC][0-9a-z]{6,}ZZZ$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(stringMin5Max10.safeParse("1234")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^[\\\\s\\\\S]{5,10}$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(connectionString.safeParse("mongodb://host:1234/defaultauthdb?authSourceadmin")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^mongodb:\\\\/\\\\/(\\\\w+:\\\\w+@)?\\\\w+:-?\\\\d+(\\\\/(\\\\w+)?(\\\\?(\\\\w+=\\\\w+(&\\\\w+=\\\\w+)*)?)?)?$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(stringStartsWithMax5.safeParse("1hell")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^hello.*$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@@ -0,0 +1,109 @@
|
||||
import { getErrorMap } from "../errors.js";
|
||||
import defaultErrorMap from "../locales/en.js";
|
||||
export const makeIssue = (params) => {
|
||||
const { data, path, errorMaps, issueData } = params;
|
||||
const fullPath = [...path, ...(issueData.path || [])];
|
||||
const fullIssue = {
|
||||
...issueData,
|
||||
path: fullPath,
|
||||
};
|
||||
if (issueData.message !== undefined) {
|
||||
return {
|
||||
...issueData,
|
||||
path: fullPath,
|
||||
message: issueData.message,
|
||||
};
|
||||
}
|
||||
let errorMessage = "";
|
||||
const maps = errorMaps
|
||||
.filter((m) => !!m)
|
||||
.slice()
|
||||
.reverse();
|
||||
for (const map of maps) {
|
||||
errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;
|
||||
}
|
||||
return {
|
||||
...issueData,
|
||||
path: fullPath,
|
||||
message: errorMessage,
|
||||
};
|
||||
};
|
||||
export const EMPTY_PATH = [];
|
||||
export function addIssueToContext(ctx, issueData) {
|
||||
const overrideMap = getErrorMap();
|
||||
const issue = makeIssue({
|
||||
issueData: issueData,
|
||||
data: ctx.data,
|
||||
path: ctx.path,
|
||||
errorMaps: [
|
||||
ctx.common.contextualErrorMap, // contextual error map is first priority
|
||||
ctx.schemaErrorMap, // then schema-bound map if available
|
||||
overrideMap, // then global override map
|
||||
overrideMap === defaultErrorMap ? undefined : defaultErrorMap, // then global default map
|
||||
].filter((x) => !!x),
|
||||
});
|
||||
ctx.common.issues.push(issue);
|
||||
}
|
||||
export class ParseStatus {
|
||||
constructor() {
|
||||
this.value = "valid";
|
||||
}
|
||||
dirty() {
|
||||
if (this.value === "valid")
|
||||
this.value = "dirty";
|
||||
}
|
||||
abort() {
|
||||
if (this.value !== "aborted")
|
||||
this.value = "aborted";
|
||||
}
|
||||
static mergeArray(status, results) {
|
||||
const arrayValue = [];
|
||||
for (const s of results) {
|
||||
if (s.status === "aborted")
|
||||
return INVALID;
|
||||
if (s.status === "dirty")
|
||||
status.dirty();
|
||||
arrayValue.push(s.value);
|
||||
}
|
||||
return { status: status.value, value: arrayValue };
|
||||
}
|
||||
static async mergeObjectAsync(status, pairs) {
|
||||
const syncPairs = [];
|
||||
for (const pair of pairs) {
|
||||
const key = await pair.key;
|
||||
const value = await pair.value;
|
||||
syncPairs.push({
|
||||
key,
|
||||
value,
|
||||
});
|
||||
}
|
||||
return ParseStatus.mergeObjectSync(status, syncPairs);
|
||||
}
|
||||
static mergeObjectSync(status, pairs) {
|
||||
const finalObject = {};
|
||||
for (const pair of pairs) {
|
||||
const { key, value } = pair;
|
||||
if (key.status === "aborted")
|
||||
return INVALID;
|
||||
if (value.status === "aborted")
|
||||
return INVALID;
|
||||
if (key.status === "dirty")
|
||||
status.dirty();
|
||||
if (value.status === "dirty")
|
||||
status.dirty();
|
||||
if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
|
||||
finalObject[key.value] = value.value;
|
||||
}
|
||||
}
|
||||
return { status: status.value, value: finalObject };
|
||||
}
|
||||
}
|
||||
export const INVALID = Object.freeze({
|
||||
status: "aborted",
|
||||
});
|
||||
export const DIRTY = (value) => ({ status: "dirty", value });
|
||||
export const OK = (value) => ({ status: "valid", value });
|
||||
export const isAborted = (x) => x.status === "aborted";
|
||||
export const isDirty = (x) => x.status === "dirty";
|
||||
export const isValid = (x) => x.status === "valid";
|
||||
export const isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @fileoverview Common utils for directives.
|
||||
*
|
||||
* This file contains only shared items for directives.
|
||||
* If you make a utility for rules, please see `../rules/utils/ast-utils.js`.
|
||||
*
|
||||
* @author gfyoung <https://github.com/gfyoung>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const directivesPattern =
|
||||
/^(eslint(?:-env|-enable|-disable(?:(?:-next)?-line)?)?|exported|globals?)(?:\s|$)/u;
|
||||
|
||||
module.exports = {
|
||||
directivesPattern,
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2015.iterable" />
|
||||
|
||||
interface ObjectConstructor {
|
||||
/**
|
||||
* Returns an object created by key-value entries for properties and methods
|
||||
* @param entries An iterable object that contains key-value entries for properties and methods.
|
||||
*/
|
||||
fromEntries<T = any>(entries: Iterable<readonly [PropertyKey, T]>): { [k: string]: T; };
|
||||
|
||||
/**
|
||||
* Returns an object created by key-value entries for properties and methods
|
||||
* @param entries An iterable object that contains key-value entries for properties and methods.
|
||||
*/
|
||||
fromEntries(entries: Iterable<readonly any[]>): any;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @fileoverview Types for this package.
|
||||
*/
|
||||
import type { ConfigObject } from "@eslint/core";
|
||||
/** @deprecated Use `ConfigObject` instead. */
|
||||
export type Config = ConfigObject;
|
||||
/**
|
||||
* Infinite array type.
|
||||
*/
|
||||
export type InfiniteArray<T> = T | InfiniteArray<T>[];
|
||||
/**
|
||||
* A config object that may appear inside of `extends`.
|
||||
* `basePath` and nested `extends` are not allowed on extension config objects.
|
||||
*/
|
||||
export type ExtensionConfigObject = Omit<ConfigObject, "basePath"> & {
|
||||
extends?: never;
|
||||
};
|
||||
/**
|
||||
* The type of array element in the `extends` property after flattening.
|
||||
*/
|
||||
export type SimpleExtendsElement = string | ExtensionConfigObject;
|
||||
/**
|
||||
* The type of array element in the `extends` property before flattening.
|
||||
*/
|
||||
export type ExtendsElement = SimpleExtendsElement | InfiniteArray<ExtensionConfigObject>;
|
||||
/**
|
||||
* Config with extends. Valid only inside of `defineConfig()`.
|
||||
*/
|
||||
export interface ConfigWithExtends extends ConfigObject {
|
||||
extends?: ExtendsElement[];
|
||||
}
|
||||
export type ConfigWithExtendsArray = InfiniteArray<ConfigWithExtends>[];
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow returning value from constructor.
|
||||
* @author Pig Fang <https://github.com/g-plane>
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "Disallow returning value from constructor",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-constructor-return",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
fixable: null,
|
||||
|
||||
messages: {
|
||||
unexpected: "Unexpected return statement in constructor.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const stack = [];
|
||||
|
||||
return {
|
||||
onCodePathStart(_, node) {
|
||||
stack.push(node);
|
||||
},
|
||||
onCodePathEnd() {
|
||||
stack.pop();
|
||||
},
|
||||
ReturnStatement(node) {
|
||||
const last = stack.at(-1);
|
||||
|
||||
if (!last.parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
last.parent.type === "MethodDefinition" &&
|
||||
last.parent.kind === "constructor" &&
|
||||
node.argument
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unexpected",
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const description = "a description";
|
||||
|
||||
// test("passing `description` to schema should add a description", () => {
|
||||
// expect(z.string({ description }).description).toEqual(description);
|
||||
// expect(z.number({ description }).description).toEqual(description);
|
||||
// expect(z.boolean({ description }).description).toEqual(description);
|
||||
// });
|
||||
|
||||
test(".describe", () => {
|
||||
expect(z.string().describe(description).description).toEqual(description);
|
||||
expect(z.number().describe(description).description).toEqual(description);
|
||||
expect(z.boolean().describe(description).description).toEqual(description);
|
||||
});
|
||||
|
||||
test("adding description with z.globalRegistry", () => {
|
||||
const schema = z.string();
|
||||
z.core.globalRegistry.add(schema, { description });
|
||||
z.core.globalRegistry.get(schema);
|
||||
expect(schema.description).toEqual(description);
|
||||
});
|
||||
|
||||
// in Zod 4 descriptions are not inherited
|
||||
// test("description should carry over to chained schemas", () => {
|
||||
// const schema = z.string().describe(description);
|
||||
// expect(schema.description).toEqual(description);
|
||||
// expect(schema.optional().description).toEqual(description);
|
||||
// expect(schema.optional().nullable().default("default").description).toEqual(description);
|
||||
// });
|
||||
Reference in New Issue
Block a user