WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
/* eslint-disable @typescript-eslint/no-namespace, no-restricted-syntax */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Linter = void 0;
|
||||
const eslint_1 = require("eslint");
|
||||
/**
|
||||
* The Linter object does the actual evaluation of the JavaScript code. It doesn't do any filesystem operations, it
|
||||
* simply parses and reports on the code. In particular, the Linter object does not process configuration objects
|
||||
* or files.
|
||||
*/
|
||||
class Linter extends eslint_1.Linter {
|
||||
}
|
||||
exports.Linter = Linter;
|
||||
@@ -0,0 +1,265 @@
|
||||
import * as vite from 'vite';
|
||||
import { InlineConfig, UserConfig as UserConfig$1, Plugin, ResolvedConfig as ResolvedConfig$1, ViteDevServer, LogLevel, LoggerOptions, Logger as Logger$1 } from 'vite';
|
||||
export { vite as Vite };
|
||||
export { esbuildVersion, isCSSRequest, isFileLoadingAllowed, parseAst, parseAstAsync, rollupVersion, version as viteVersion } from 'vite';
|
||||
import { IncomingMessage } from 'node:http';
|
||||
import { R as ResolvedConfig, e as UserConfig, f as VitestRunMode, g as VitestOptions, V as Vitest, A as ApiConfig, L as Logger, h as TestSpecification, T as TestProject, P as PoolWorker, i as PoolOptions, j as WorkerRequest, k as TestSequencer } from './chunks/reporters.d.DtoKVV2s.js';
|
||||
export { M as AgentReporter, B as BaseCoverageOptions, l as BaseReporter, m as BenchmarkBuiltinReporters, n as BenchmarkReporter, o as BenchmarkReportsMap, p as BenchmarkUserOptions, q as BrowserBuiltinProvider, r as BrowserCommand, s as BrowserCommandContext, t as BrowserConfigOptions, u as BrowserInstanceOption, v as BrowserModuleMocker, w as BrowserOrchestrator, x as BrowserProvider, y as BrowserProviderOption, z as BrowserScript, D as BrowserServerFactory, E as BrowserServerOptions, G as BrowserServerState, H as BrowserServerStateSession, J as BuiltinEnvironment, K as BuiltinReporterOptions, N as BuiltinReporters, O as CSSModuleScopeStrategy, Q as CoverageInstrumenter, S as CoverageIstanbulOptions, C as CoverageOptions, X as CoverageProvider, Y as CoverageProviderModule, Z as CoverageReporter, _ as CoverageV8Options, $ as CustomProviderOptions, a0 as DefaultReporter, a1 as DepsOptimizationOptions, a2 as DotReporter, a3 as EnvironmentOptions, a4 as GithubActionsReporter, a5 as HTMLOptions, a6 as HangingProcessReporter, I as InlineConfig, a7 as InstrumenterOptions, a8 as JUnitOptions, a9 as JUnitReporter, aa as JsonAssertionResult, ab as JsonOptions, ac as JsonReporter, ad as JsonTestResult, ae as JsonTestResults, M as MinimalReporter, af as ModuleDiagnostic, ag as OnServerRestartHandler, ah as OnTestsRerunHandler, ai as ParentProjectBrowser, aj as Pool, ak as PoolRunnerInitializer, al as PoolTask, am as ProjectBrowser, an as ProjectConfig, ao as ReportContext, ap as ReportedHookContext, aq as Reporter, ar as ReportersMap, as as ResolveSnapshotPathHandler, at as ResolveSnapshotPathHandlerContext, au as ResolvedBrowserOptions, av as ResolvedCoverageOptions, aw as ResolvedProjectConfig, ax as SerializedTestProject, ay as TapFlatReporter, az as TapReporter, aA as TaskOptions, aB as TestCase, aC as TestCollection, aD as TestDiagnostic, aE as TestModule, aF as TestModuleState, aG as TestResult, aH as TestResultFailed, aI as TestResultPassed, aJ as TestResultSkipped, aK as TestRunEndReason, aL as TestRunResult, aM as TestSequencerConstructor, aN as TestSpecificationOptions, aO as TestState, aP as TestSuite, aQ as TestSuiteState, aR as ToMatchScreenshotComparators, aS as ToMatchScreenshotOptions, aT as TypecheckConfig, U as UserWorkspaceConfig, aU as VerboseBenchmarkReporter, aV as VerboseReporter, aW as VitestEnvironment, aX as VitestPackageInstaller, W as WatcherTriggerPattern, aY as WorkerResponse, aZ as _BrowserNames, a_ as experimental_getRunnerTask } from './chunks/reporters.d.DtoKVV2s.js';
|
||||
export { C as CacheKeyIdGenerator, a as CacheKeyIdGeneratorContext, V as VitestPluginContext } from './chunks/plugin.d.DwFIiJ7i.js';
|
||||
export { BaseCoverageProvider } from './coverage.js';
|
||||
import { Awaitable } from '@vitest/utils';
|
||||
export { SerializedError } from '@vitest/utils';
|
||||
import { R as RuntimeRPC } from './chunks/rpc.d.B_8sPU0w.js';
|
||||
import { Writable } from 'node:stream';
|
||||
import { C as ContextRPC } from './chunks/worker.d.ZpHpO4yb.js';
|
||||
export { T as TestExecutionType } from './chunks/worker.d.ZpHpO4yb.js';
|
||||
import { Debugger } from 'obug';
|
||||
import './chunks/global.d.DVsSRdQ5.js';
|
||||
export { Task as RunnerTask, TaskResult as RunnerTaskResult, TaskResultPack as RunnerTaskResultPack, Test as RunnerTestCase, File as RunnerTestFile, Suite as RunnerTestSuite, SequenceHooks, SequenceSetupFiles } from '@vitest/runner';
|
||||
export { c as RuntimeConfig } from './chunks/config.d.A1h_Y6Jt.js';
|
||||
export { generateFileHash } from '@vitest/runner/utils';
|
||||
export { CDPSession } from 'vitest/browser';
|
||||
import './chunks/traces.d.D2T_R8rx.js';
|
||||
import './chunks/browser.d.BcoexmFG.js';
|
||||
import '@vitest/pretty-format';
|
||||
import '@vitest/snapshot';
|
||||
import '@vitest/utils/diff';
|
||||
import '@vitest/expect';
|
||||
import 'vitest/optional-types.js';
|
||||
import './chunks/benchmark.d.DAaHLpsq.js';
|
||||
import 'tinybench';
|
||||
import '@vitest/mocker';
|
||||
import '@vitest/utils/source-map';
|
||||
import './chunks/coverage.d.BZtK59WP.js';
|
||||
import '@vitest/snapshot/manager';
|
||||
import 'node:console';
|
||||
import 'node:fs';
|
||||
import 'vite/module-runner';
|
||||
import './chunks/environment.d.CrsxCzP1.js';
|
||||
|
||||
type RawErrsMap = Map<string, TscErrorInfo[]>;
|
||||
interface TscErrorInfo {
|
||||
filePath: string;
|
||||
errCode: number;
|
||||
errMsg: string;
|
||||
line: number;
|
||||
column: number;
|
||||
}
|
||||
interface CollectLineNumbers {
|
||||
target: number;
|
||||
next: number;
|
||||
prev?: number;
|
||||
}
|
||||
type CollectLines = { [key in keyof CollectLineNumbers] : string };
|
||||
interface RootAndTarget {
|
||||
root: string;
|
||||
targetAbsPath: string;
|
||||
}
|
||||
type Context = RootAndTarget & {
|
||||
rawErrsMap: RawErrsMap;
|
||||
openedDirs: Set<string>;
|
||||
lastActivePath?: string;
|
||||
};
|
||||
|
||||
declare function isValidApiRequest(config: ResolvedConfig, req: IncomingMessage): boolean;
|
||||
|
||||
declare function escapeTestName(label: string, dynamic: boolean): string;
|
||||
|
||||
interface CliOptions extends UserConfig {
|
||||
/**
|
||||
* Override the watch mode
|
||||
*/
|
||||
run?: boolean;
|
||||
/**
|
||||
* Removes colors from the console output
|
||||
*/
|
||||
color?: boolean;
|
||||
/**
|
||||
* Output collected tests as JSON or to a file
|
||||
*/
|
||||
json?: string | boolean;
|
||||
/**
|
||||
* Output collected test files only
|
||||
*/
|
||||
filesOnly?: boolean;
|
||||
/**
|
||||
* Parse files statically instead of running them to collect tests
|
||||
* @experimental
|
||||
*/
|
||||
staticParse?: boolean;
|
||||
/**
|
||||
* How many tests to process at the same time
|
||||
* @experimental
|
||||
*/
|
||||
staticParseConcurrency?: number;
|
||||
/**
|
||||
* Override vite config's configLoader from CLI.
|
||||
* Use `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly (default: `bundle`).
|
||||
* This is only available with **vite version 6.1.0** and above.
|
||||
* @experimental
|
||||
*/
|
||||
configLoader?: InlineConfig extends {
|
||||
configLoader?: infer T;
|
||||
} ? T : never;
|
||||
}
|
||||
/**
|
||||
* Start Vitest programmatically
|
||||
*
|
||||
* Returns a Vitest instance if initialized successfully.
|
||||
*/
|
||||
declare function startVitest(mode: VitestRunMode, cliFilters?: string[], options?: CliOptions, viteOverrides?: UserConfig$1, vitestOptions?: VitestOptions): Promise<Vitest>;
|
||||
|
||||
interface CliParseOptions {
|
||||
allowUnknownOptions?: boolean;
|
||||
}
|
||||
declare function parseCLI(argv: string | string[], config?: CliParseOptions): {
|
||||
filter: string[];
|
||||
options: CliOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated Internal function
|
||||
*/
|
||||
declare function resolveApiServerConfig<Options extends ApiConfig & Omit<UserConfig, "expect">>(options: Options, defaultPort: number, parentApi?: ApiConfig, logger?: Logger): ApiConfig | undefined;
|
||||
|
||||
declare function createVitest(mode: VitestRunMode, options: CliOptions, viteOverrides?: UserConfig$1, vitestOptions?: VitestOptions): Promise<Vitest>;
|
||||
|
||||
declare class FilesNotFoundError extends Error {
|
||||
code: string;
|
||||
constructor(mode: "test" | "benchmark");
|
||||
}
|
||||
declare class GitNotFoundError extends Error {
|
||||
code: string;
|
||||
constructor();
|
||||
}
|
||||
|
||||
declare function VitestPlugin(options?: UserConfig, vitest?: Vitest): Promise<Plugin[]>;
|
||||
|
||||
declare function resolveConfig(options?: UserConfig, viteOverrides?: UserConfig$1): Promise<{
|
||||
vitestConfig: ResolvedConfig;
|
||||
viteConfig: ResolvedConfig$1;
|
||||
}>;
|
||||
|
||||
declare function resolveFsAllow(projectRoot: string, rootConfigFile: string | false | undefined): string[];
|
||||
|
||||
type RunWithFiles = (files: TestSpecification[], invalidates?: string[]) => Promise<void>;
|
||||
interface ProcessPool {
|
||||
name: string;
|
||||
runTests: RunWithFiles;
|
||||
collectTests: RunWithFiles;
|
||||
close?: () => Awaitable<void>;
|
||||
}
|
||||
declare function getFilePoolName(project: TestProject): ResolvedConfig["pool"];
|
||||
|
||||
interface MethodsOptions {
|
||||
cacheFs?: boolean;
|
||||
collect?: boolean;
|
||||
}
|
||||
declare function createMethodsRPC(project: TestProject, methodsOptions?: MethodsOptions): RuntimeRPC;
|
||||
|
||||
/** @experimental */
|
||||
declare class ForksPoolWorker implements PoolWorker {
|
||||
readonly name: string;
|
||||
readonly cacheFs: boolean;
|
||||
protected readonly entrypoint: string;
|
||||
protected execArgv: string[];
|
||||
protected env: Partial<NodeJS.ProcessEnv>;
|
||||
private _fork?;
|
||||
private stdout;
|
||||
private stderr;
|
||||
constructor(options: PoolOptions);
|
||||
on(event: string, callback: (arg: any) => void): void;
|
||||
off(event: string, callback: (arg: any) => void): void;
|
||||
send(message: WorkerRequest): void;
|
||||
start(): Promise<void>;
|
||||
stop(): Promise<void>;
|
||||
deserialize(data: unknown): unknown;
|
||||
private get fork();
|
||||
}
|
||||
|
||||
/** @experimental */
|
||||
declare class ThreadsPoolWorker implements PoolWorker {
|
||||
readonly name: string;
|
||||
protected readonly entrypoint: string;
|
||||
protected execArgv: string[];
|
||||
protected env: Partial<NodeJS.ProcessEnv>;
|
||||
private _thread?;
|
||||
private stdout;
|
||||
private stderr;
|
||||
constructor(options: PoolOptions);
|
||||
on(event: string, callback: (arg: any) => void): void;
|
||||
off(event: string, callback: (arg: any) => void): void;
|
||||
send(message: WorkerRequest): void;
|
||||
start(): Promise<void>;
|
||||
stop(): Promise<void>;
|
||||
deserialize(data: unknown): unknown;
|
||||
private get thread();
|
||||
}
|
||||
|
||||
/** @experimental */
|
||||
declare class TypecheckPoolWorker implements PoolWorker {
|
||||
readonly name: string;
|
||||
private readonly project;
|
||||
private _eventEmitter;
|
||||
constructor(options: PoolOptions);
|
||||
start(): Promise<void>;
|
||||
stop(): Promise<void>;
|
||||
canReuse(): boolean;
|
||||
send(message: WorkerRequest): void;
|
||||
on(event: string, callback: (arg: any) => any): void;
|
||||
off(event: string, callback: (arg: any) => any): void;
|
||||
deserialize(data: unknown): unknown;
|
||||
}
|
||||
|
||||
/** @experimental */
|
||||
declare class VmForksPoolWorker extends ForksPoolWorker {
|
||||
readonly name = "vmForks";
|
||||
readonly reportMemory: true;
|
||||
protected readonly entrypoint: string;
|
||||
constructor(options: PoolOptions);
|
||||
canReuse(): boolean;
|
||||
}
|
||||
|
||||
/** @experimental */
|
||||
declare class VmThreadsPoolWorker extends ThreadsPoolWorker {
|
||||
readonly name = "vmThreads";
|
||||
readonly reportMemory: true;
|
||||
protected readonly entrypoint: string;
|
||||
constructor(options: PoolOptions);
|
||||
canReuse(): boolean;
|
||||
}
|
||||
|
||||
declare class BaseSequencer implements TestSequencer {
|
||||
protected ctx: Vitest;
|
||||
constructor(ctx: Vitest);
|
||||
shard(files: TestSpecification[]): Promise<TestSpecification[]>;
|
||||
sort(files: TestSpecification[]): Promise<TestSpecification[]>;
|
||||
private calculateShardRange;
|
||||
}
|
||||
|
||||
declare function registerConsoleShortcuts(ctx: Vitest, stdin: NodeJS.ReadStream | undefined, stdout: NodeJS.WriteStream | Writable): () => void;
|
||||
|
||||
interface WorkerContext extends ContextRPC {}
|
||||
|
||||
/**
|
||||
* Check if the url is allowed to be served, via the `server.fs` config.
|
||||
* @deprecated Use the `isFileLoadingAllowed` function instead.
|
||||
*/
|
||||
declare function isFileServingAllowed(config: ResolvedConfig$1, url: string): boolean;
|
||||
declare function isFileServingAllowed(url: string, server: ViteDevServer): boolean;
|
||||
|
||||
declare function createViteLogger(console: Logger, level?: LogLevel, options?: LoggerOptions): Logger$1;
|
||||
|
||||
declare const rootDir: string;
|
||||
declare const distDir: string;
|
||||
|
||||
declare function createDebugger(namespace: `vitest:${string}`): Debugger | undefined;
|
||||
|
||||
declare const version: string;
|
||||
|
||||
declare const createViteServer: typeof vite.createServer;
|
||||
|
||||
declare const rolldownVersion: string | undefined;
|
||||
|
||||
export { ApiConfig, BaseSequencer, ForksPoolWorker, GitNotFoundError, PoolOptions, PoolWorker, ResolvedConfig, TestProject, TestSequencer, TestSpecification, UserConfig as TestUserConfig, FilesNotFoundError as TestsNotFoundError, ThreadsPoolWorker, TypecheckPoolWorker, Vitest, VitestOptions, VitestPlugin, VitestRunMode, VmForksPoolWorker, VmThreadsPoolWorker, WorkerRequest, createDebugger, createMethodsRPC, createViteLogger, createViteServer, createVitest, distDir, escapeTestName, getFilePoolName, isFileServingAllowed, isValidApiRequest, parseCLI, registerConsoleShortcuts, resolveApiServerConfig, resolveConfig, resolveFsAllow, rolldownVersion, rootDir, startVitest, version };
|
||||
export type { CliOptions, CliParseOptions, ProcessPool, CollectLineNumbers as TypeCheckCollectLineNumbers, CollectLines as TypeCheckCollectLines, Context as TypeCheckContext, TscErrorInfo as TypeCheckErrorInfo, RawErrsMap as TypeCheckRawErrorsMap, RootAndTarget as TypeCheckRootAndTarget, WorkerContext };
|
||||
@@ -0,0 +1,597 @@
|
||||
/*! *****************************************************************************
|
||||
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 Array<T> {
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find<S extends T>(predicate: (value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined;
|
||||
find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found,
|
||||
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Changes all array elements from `start` to `end` index to a static `value` and returns the modified array
|
||||
* @param value value to fill array section with
|
||||
* @param start index to start filling the array at. If start is negative, it is treated as
|
||||
* length+start where length is the length of the array.
|
||||
* @param end index to stop filling the array at. If end is negative, it is treated as
|
||||
* length+end.
|
||||
*/
|
||||
fill(value: T, start?: number, end?: number): this;
|
||||
|
||||
/**
|
||||
* Returns the this object after copying a section of the array identified by start and end
|
||||
* to the same array starting at position target
|
||||
* @param target If target is negative, it is treated as length+target where length is the
|
||||
* length of the array.
|
||||
* @param start If start is negative, it is treated as length+start. If end is negative, it
|
||||
* is treated as length+end.
|
||||
* @param end If not specified, length of the this object is used as its default value.
|
||||
*/
|
||||
copyWithin(target: number, start: number, end?: number): this;
|
||||
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string;
|
||||
}
|
||||
|
||||
interface ArrayConstructor {
|
||||
/**
|
||||
* Creates an array from an array-like object.
|
||||
* @param arrayLike An array-like object to convert to an array.
|
||||
*/
|
||||
from<T>(arrayLike: ArrayLike<T>): T[];
|
||||
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
* @param arrayLike An array-like object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array from a set of elements.
|
||||
* @param items A set of elements to include in the new array object.
|
||||
*/
|
||||
of<T>(...items: T[]): T[];
|
||||
}
|
||||
|
||||
interface DateConstructor {
|
||||
new (value: number | string | Date): Date;
|
||||
}
|
||||
|
||||
interface Function {
|
||||
/**
|
||||
* Returns the name of the function. Function names are read-only and can not be changed.
|
||||
*/
|
||||
readonly name: string;
|
||||
}
|
||||
|
||||
interface Math {
|
||||
/**
|
||||
* Returns the number of leading zero bits in the 32-bit binary representation of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
clz32(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the result of 32-bit multiplication of two numbers.
|
||||
* @param x First number
|
||||
* @param y Second number
|
||||
*/
|
||||
imul(x: number, y: number): number;
|
||||
|
||||
/**
|
||||
* Returns the sign of the x, indicating whether x is positive, negative or zero.
|
||||
* @param x The numeric expression to test
|
||||
*/
|
||||
sign(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the base 10 logarithm of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log10(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the base 2 logarithm of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log2(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm of 1 + x.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log1p(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the result of (e^x - 1), which is an implementation-dependent approximation to
|
||||
* subtracting 1 from the exponential function of x (e raised to the power of x, where e
|
||||
* is the base of the natural logarithms).
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
expm1(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cosine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
cosh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic sine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
sinh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic tangent of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
tanh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cosine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
acosh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic sine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
asinh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic tangent of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
atanh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the square root of the sum of squares of its arguments.
|
||||
* @param values Values to compute the square root for.
|
||||
* If no arguments are passed, the result is +0.
|
||||
* If there is only one argument, the result is the absolute value.
|
||||
* If any argument is +Infinity or -Infinity, the result is +Infinity.
|
||||
* If any argument is NaN, the result is NaN.
|
||||
* If all arguments are either +0 or −0, the result is +0.
|
||||
*/
|
||||
hypot(...values: number[]): number;
|
||||
|
||||
/**
|
||||
* Returns the integral part of the a numeric expression, x, removing any fractional digits.
|
||||
* If x is already an integer, the result is x.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
trunc(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the nearest single precision float representation of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
fround(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns an implementation-dependent approximation to the cube root of number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
cbrt(x: number): number;
|
||||
}
|
||||
|
||||
interface NumberConstructor {
|
||||
/**
|
||||
* The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1
|
||||
* that is representable as a Number value, which is approximately:
|
||||
* 2.2204460492503130808472633361816 x 10−16.
|
||||
*/
|
||||
readonly EPSILON: number;
|
||||
|
||||
/**
|
||||
* Returns true if passed value is finite.
|
||||
* Unlike the global isFinite, Number.isFinite doesn't forcibly convert the parameter to a
|
||||
* number. Only finite values of the type number, result in true.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isFinite(number: unknown): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the value passed is an integer, false otherwise.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isInteger(number: unknown): boolean;
|
||||
|
||||
/**
|
||||
* Returns a Boolean value that indicates whether a value is the reserved value NaN (not a
|
||||
* number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter
|
||||
* to a number. Only values of the type number, that are also NaN, result in true.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isNaN(number: unknown): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the value passed is a safe integer.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isSafeInteger(number: unknown): boolean;
|
||||
|
||||
/**
|
||||
* The value of the largest integer n such that n and n + 1 are both exactly representable as
|
||||
* a Number value.
|
||||
* The value of Number.MAX_SAFE_INTEGER is 9007199254740991 2^53 − 1.
|
||||
*/
|
||||
readonly MAX_SAFE_INTEGER: number;
|
||||
|
||||
/**
|
||||
* The value of the smallest integer n such that n and n − 1 are both exactly representable as
|
||||
* a Number value.
|
||||
* The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)).
|
||||
*/
|
||||
readonly MIN_SAFE_INTEGER: number;
|
||||
|
||||
/**
|
||||
* Converts a string to a floating-point number.
|
||||
* @param string A string that contains a floating-point number.
|
||||
*/
|
||||
parseFloat(string: string): number;
|
||||
|
||||
/**
|
||||
* Converts A string to an integer.
|
||||
* @param string A string to convert into a number.
|
||||
* @param radix A value between 2 and 36 that specifies the base of the number in `string`.
|
||||
* If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
|
||||
* All other strings are considered decimal.
|
||||
*/
|
||||
parseInt(string: string, radix?: number): number;
|
||||
}
|
||||
|
||||
interface ObjectConstructor {
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param source The source object from which to copy properties.
|
||||
*/
|
||||
assign<T extends {}, U>(target: T, source: U): T & U;
|
||||
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param source1 The first source object from which to copy properties.
|
||||
* @param source2 The second source object from which to copy properties.
|
||||
*/
|
||||
assign<T extends {}, U, V>(target: T, source1: U, source2: V): T & U & V;
|
||||
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param source1 The first source object from which to copy properties.
|
||||
* @param source2 The second source object from which to copy properties.
|
||||
* @param source3 The third source object from which to copy properties.
|
||||
*/
|
||||
assign<T extends {}, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
|
||||
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param sources One or more source objects from which to copy properties
|
||||
*/
|
||||
assign(target: object, ...sources: any[]): any;
|
||||
|
||||
/**
|
||||
* Returns an array of all symbol properties found directly on object o.
|
||||
* @param o Object to retrieve the symbols from.
|
||||
*/
|
||||
getOwnPropertySymbols(o: any): symbol[];
|
||||
|
||||
/**
|
||||
* Returns the names of the enumerable string properties and methods of an object.
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
keys(o: {}): string[];
|
||||
|
||||
/**
|
||||
* Returns true if the values are the same value, false otherwise.
|
||||
* @param value1 The first value.
|
||||
* @param value2 The second value.
|
||||
*/
|
||||
is(value1: any, value2: any): boolean;
|
||||
|
||||
/**
|
||||
* Sets the prototype of a specified object o to object proto or null. Returns the object o.
|
||||
* @param o The object to change its prototype.
|
||||
* @param proto The value of the new prototype or null.
|
||||
*/
|
||||
setPrototypeOf(o: any, proto: object | null): any;
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find<S extends T>(predicate: (value: T, index: number, obj: readonly T[]) => value is S, thisArg?: any): S | undefined;
|
||||
find(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found,
|
||||
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): number;
|
||||
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
* Returns a string indicating the flags of the regular expression in question. This field is read-only.
|
||||
* The characters in this string are sequenced and concatenated in the following order:
|
||||
*
|
||||
* - "g" for global
|
||||
* - "i" for ignoreCase
|
||||
* - "m" for multiline
|
||||
* - "u" for unicode
|
||||
* - "y" for sticky
|
||||
*
|
||||
* If no flags are set, the value is the empty string.
|
||||
*/
|
||||
readonly flags: string;
|
||||
|
||||
/**
|
||||
* Returns a Boolean value indicating the state of the sticky flag (y) used with a regular
|
||||
* expression. Default is false. Read-only.
|
||||
*/
|
||||
readonly sticky: boolean;
|
||||
|
||||
/**
|
||||
* Returns a Boolean value indicating the state of the Unicode flag (u) used with a regular
|
||||
* expression. Default is false. Read-only.
|
||||
*/
|
||||
readonly unicode: boolean;
|
||||
}
|
||||
|
||||
interface RegExpConstructor {
|
||||
new (pattern: RegExp | string, flags?: string): RegExp;
|
||||
(pattern: RegExp | string, flags?: string): RegExp;
|
||||
}
|
||||
|
||||
interface String {
|
||||
/**
|
||||
* Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point
|
||||
* value of the UTF-16 encoded code point starting at the string element at position pos in
|
||||
* the String resulting from converting this object to a String.
|
||||
* If there is no element at that position, the result is undefined.
|
||||
* If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos.
|
||||
*/
|
||||
codePointAt(pos: number): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns true if searchString appears as a substring of the result of converting this
|
||||
* object to a String, at one or more positions that are
|
||||
* greater than or equal to position; otherwise, returns false.
|
||||
* @param searchString search string
|
||||
* @param position If position is undefined, 0 is assumed, so as to search all of the String.
|
||||
*/
|
||||
includes(searchString: string, position?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
* same as the corresponding elements of this object (converted to a String) starting at
|
||||
* endPosition – length(this). Otherwise returns false.
|
||||
*/
|
||||
endsWith(searchString: string, endPosition?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns the String value result of normalizing the string into the normalization form
|
||||
* named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.
|
||||
* @param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default
|
||||
* is "NFC"
|
||||
*/
|
||||
normalize(form: "NFC" | "NFD" | "NFKC" | "NFKD"): string;
|
||||
|
||||
/**
|
||||
* Returns the String value result of normalizing the string into the normalization form
|
||||
* named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.
|
||||
* @param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default
|
||||
* is "NFC"
|
||||
*/
|
||||
normalize(form?: string): string;
|
||||
|
||||
/**
|
||||
* Returns a String value that is made from count copies appended together. If count is 0,
|
||||
* the empty string is returned.
|
||||
* @param count number of copies to append
|
||||
*/
|
||||
repeat(count: number): string;
|
||||
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
* same as the corresponding elements of this object (converted to a String) starting at
|
||||
* position. Otherwise returns false.
|
||||
*/
|
||||
startsWith(searchString: string, position?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns an `<a>` HTML anchor element and sets the name attribute to the text value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
* @param name
|
||||
*/
|
||||
anchor(name: string): string;
|
||||
|
||||
/**
|
||||
* Returns a `<big>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
big(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<blink>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
blink(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<b>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
bold(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<tt>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
fixed(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<font>` HTML element and sets the color attribute value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
fontcolor(color: string): string;
|
||||
|
||||
/**
|
||||
* Returns a `<font>` HTML element and sets the size attribute value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
fontsize(size: number): string;
|
||||
|
||||
/**
|
||||
* Returns a `<font>` HTML element and sets the size attribute value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
fontsize(size: string): string;
|
||||
|
||||
/**
|
||||
* Returns an `<i>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
italics(): string;
|
||||
|
||||
/**
|
||||
* Returns an `<a>` HTML element and sets the href attribute value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
link(url: string): string;
|
||||
|
||||
/**
|
||||
* Returns a `<small>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
small(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<strike>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
strike(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<sub>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
sub(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<sup>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
sup(): string;
|
||||
}
|
||||
|
||||
interface StringConstructor {
|
||||
/**
|
||||
* Return the String value whose elements are, in order, the elements in the List elements.
|
||||
* If length is 0, the empty string is returned.
|
||||
*/
|
||||
fromCodePoint(...codePoints: number[]): string;
|
||||
|
||||
/**
|
||||
* String.raw is usually used as a tag function of a Tagged Template String. When called as
|
||||
* such, the first argument will be a well formed template call site object and the rest
|
||||
* parameter will contain the substitution values. It can also be called directly, for example,
|
||||
* to interleave strings and values from your own tag function, and in this case the only thing
|
||||
* it needs from the first argument is the raw property.
|
||||
* @param template A well-formed template string call site representation.
|
||||
* @param substitutions A set of substitution values.
|
||||
*/
|
||||
raw(template: { raw: readonly string[] | ArrayLike<string>; }, ...substitutions: any[]): string;
|
||||
}
|
||||
|
||||
interface Int8Array {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Uint8Array {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Uint8ClampedArray {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Int16Array {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Uint16Array {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Int32Array {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Uint32Array {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Float32Array {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Float64Array {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
export * as core from "../core/index.js";
|
||||
export * from "./schemas.js";
|
||||
export * from "./checks.js";
|
||||
export * from "./errors.js";
|
||||
export * from "./parse.js";
|
||||
export * from "./compat.js";
|
||||
// zod-specified
|
||||
import { config } from "../core/index.js";
|
||||
import en from "../locales/en.js";
|
||||
config(en());
|
||||
export { globalRegistry, registry, config, $output, $input, $brand, clone, regexes, treeifyError, prettifyError, formatError, flattenError, TimePrecision, util, NEVER, } from "../core/index.js";
|
||||
export { toJSONSchema } from "../core/json-schema-processors.js";
|
||||
export { fromJSONSchema } from "./from-json-schema.js";
|
||||
export * as locales from "../locales/index.js";
|
||||
// iso
|
||||
// must be exported from top-level
|
||||
// https://github.com/colinhacks/zod/issues/4491
|
||||
export { ZodISODateTime, ZodISODate, ZodISOTime, ZodISODuration } from "./iso.js";
|
||||
export * as iso from "./iso.js";
|
||||
export * as coerce from "./coerce.js";
|
||||
@@ -0,0 +1,115 @@
|
||||
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: "aksara", verb: "mempunyai" },
|
||||
file: { unit: "bait", verb: "mempunyai" },
|
||||
array: { unit: "elemen", verb: "mempunyai" },
|
||||
set: { unit: "elemen", verb: "mempunyai" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const FormatDictionary: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "input",
|
||||
email: "alamat e-mel",
|
||||
url: "URL",
|
||||
emoji: "emoji",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "tarikh masa ISO",
|
||||
date: "tarikh ISO",
|
||||
time: "masa ISO",
|
||||
duration: "tempoh ISO",
|
||||
ipv4: "alamat IPv4",
|
||||
ipv6: "alamat IPv6",
|
||||
cidrv4: "julat IPv4",
|
||||
cidrv6: "julat IPv6",
|
||||
base64: "string dikodkan base64",
|
||||
base64url: "string dikodkan base64url",
|
||||
json_string: "string JSON",
|
||||
e164: "nombor E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "input",
|
||||
};
|
||||
|
||||
const TypeDictionary: {
|
||||
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
|
||||
} = {
|
||||
nan: "NaN",
|
||||
number: "nombor",
|
||||
};
|
||||
|
||||
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 `Input tidak sah: dijangka instanceof ${issue.expected}, diterima ${received}`;
|
||||
}
|
||||
return `Input tidak sah: dijangka ${expected}, diterima ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1) return `Input tidak sah: dijangka ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Pilihan tidak sah: dijangka salah satu daripada ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Terlalu besar: dijangka ${issue.origin ?? "nilai"} ${sizing.verb} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elemen"}`;
|
||||
return `Terlalu besar: dijangka ${issue.origin ?? "nilai"} adalah ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Terlalu kecil: dijangka ${issue.origin} ${sizing.verb} ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `Terlalu kecil: dijangka ${issue.origin} adalah ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `String tidak sah: mesti bermula dengan "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with") return `String tidak sah: mesti berakhir dengan "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `String tidak sah: mesti mengandungi "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `String tidak sah: mesti sepadan dengan corak ${_issue.pattern}`;
|
||||
return `${FormatDictionary[_issue.format] ?? issue.format} tidak sah`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Nombor tidak sah: perlu gandaan ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `Kunci tidak dikenali: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Kunci tidak sah dalam ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Input tidak sah";
|
||||
case "invalid_element":
|
||||
return `Nilai tidak sah dalam ${issue.origin}`;
|
||||
default:
|
||||
return `Input tidak sah`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,970 @@
|
||||
import bs58 from 'bs58';
|
||||
import {Buffer} from 'buffer';
|
||||
|
||||
import {PACKET_DATA_SIZE, SIGNATURE_LENGTH_IN_BYTES} from './constants';
|
||||
import {Connection} from '../connection';
|
||||
import {Message} from '../message';
|
||||
import {PublicKey} from '../publickey';
|
||||
import * as shortvec from '../utils/shortvec-encoding';
|
||||
import {toBuffer} from '../utils/to-buffer';
|
||||
import invariant from '../utils/assert';
|
||||
import type {Signer} from '../keypair';
|
||||
import type {Blockhash} from '../blockhash';
|
||||
import type {CompiledInstruction} from '../message';
|
||||
import {sign, verify} from '../utils/ed25519';
|
||||
import {guardedSplice} from '../utils/guarded-array-utils';
|
||||
|
||||
/** @internal */
|
||||
type MessageSignednessErrors = {
|
||||
invalid?: PublicKey[];
|
||||
missing?: PublicKey[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Transaction signature as base-58 encoded string
|
||||
*/
|
||||
export type TransactionSignature = string;
|
||||
|
||||
export const enum TransactionStatus {
|
||||
BLOCKHEIGHT_EXCEEDED,
|
||||
PROCESSED,
|
||||
TIMED_OUT,
|
||||
NONCE_INVALID,
|
||||
}
|
||||
|
||||
/**
|
||||
* Default (empty) signature
|
||||
*/
|
||||
const DEFAULT_SIGNATURE = Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
|
||||
|
||||
/**
|
||||
* Account metadata used to define instructions
|
||||
*/
|
||||
export type AccountMeta = {
|
||||
/** An account's public key */
|
||||
pubkey: PublicKey;
|
||||
/** True if an instruction requires a transaction signature matching `pubkey` */
|
||||
isSigner: boolean;
|
||||
/** True if the `pubkey` can be loaded as a read-write account. */
|
||||
isWritable: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of TransactionInstruction object fields that may be initialized at construction
|
||||
*/
|
||||
export type TransactionInstructionCtorFields = {
|
||||
keys: Array<AccountMeta>;
|
||||
programId: PublicKey;
|
||||
data?: Buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration object for Transaction.serialize()
|
||||
*/
|
||||
export type SerializeConfig = {
|
||||
/** Require all transaction signatures be present (default: true) */
|
||||
requireAllSignatures?: boolean;
|
||||
/** Verify provided signatures (default: true) */
|
||||
verifySignatures?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface TransactionInstructionJSON {
|
||||
keys: {
|
||||
pubkey: string;
|
||||
isSigner: boolean;
|
||||
isWritable: boolean;
|
||||
}[];
|
||||
programId: string;
|
||||
data: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaction Instruction class
|
||||
*/
|
||||
export class TransactionInstruction {
|
||||
/**
|
||||
* Public keys to include in this transaction
|
||||
* Boolean represents whether this pubkey needs to sign the transaction
|
||||
*/
|
||||
keys: Array<AccountMeta>;
|
||||
|
||||
/**
|
||||
* Program Id to execute
|
||||
*/
|
||||
programId: PublicKey;
|
||||
|
||||
/**
|
||||
* Program input
|
||||
*/
|
||||
data: Buffer = Buffer.alloc(0);
|
||||
|
||||
constructor(opts: TransactionInstructionCtorFields) {
|
||||
this.programId = opts.programId;
|
||||
this.keys = opts.keys;
|
||||
if (opts.data) {
|
||||
this.data = opts.data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
toJSON(): TransactionInstructionJSON {
|
||||
return {
|
||||
keys: this.keys.map(({pubkey, isSigner, isWritable}) => ({
|
||||
pubkey: pubkey.toJSON(),
|
||||
isSigner,
|
||||
isWritable,
|
||||
})),
|
||||
programId: this.programId.toJSON(),
|
||||
data: [...this.data],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pair of signature and corresponding public key
|
||||
*/
|
||||
export type SignaturePubkeyPair = {
|
||||
signature: Buffer | null;
|
||||
publicKey: PublicKey;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of Transaction object fields that may be initialized at construction
|
||||
*/
|
||||
export type TransactionCtorFields_DEPRECATED = {
|
||||
/** Optional nonce information used for offline nonce'd transactions */
|
||||
nonceInfo?: NonceInformation | null;
|
||||
/** The transaction fee payer */
|
||||
feePayer?: PublicKey | null;
|
||||
/** One or more signatures */
|
||||
signatures?: Array<SignaturePubkeyPair>;
|
||||
/** A recent blockhash */
|
||||
recentBlockhash?: Blockhash;
|
||||
};
|
||||
|
||||
// For backward compatibility; an unfortunate consequence of being
|
||||
// forced to over-export types by the documentation generator.
|
||||
// See https://github.com/solana-labs/solana/pull/25820
|
||||
export type TransactionCtorFields = TransactionCtorFields_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Blockhash-based transactions have a lifetime that are defined by
|
||||
* the blockhash they include. Any transaction whose blockhash is
|
||||
* too old will be rejected.
|
||||
*/
|
||||
export type TransactionBlockhashCtor = {
|
||||
/** The transaction fee payer */
|
||||
feePayer?: PublicKey | null;
|
||||
/** One or more signatures */
|
||||
signatures?: Array<SignaturePubkeyPair>;
|
||||
/** A recent blockhash */
|
||||
blockhash: Blockhash;
|
||||
/** the last block chain can advance to before tx is declared expired */
|
||||
lastValidBlockHeight: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Use these options to construct a durable nonce transaction.
|
||||
*/
|
||||
export type TransactionNonceCtor = {
|
||||
/** The transaction fee payer */
|
||||
feePayer?: PublicKey | null;
|
||||
minContextSlot: number;
|
||||
nonceInfo: NonceInformation;
|
||||
/** One or more signatures */
|
||||
signatures?: Array<SignaturePubkeyPair>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Nonce information to be used to build an offline Transaction.
|
||||
*/
|
||||
export type NonceInformation = {
|
||||
/** The current blockhash stored in the nonce */
|
||||
nonce: Blockhash;
|
||||
/** AdvanceNonceAccount Instruction */
|
||||
nonceInstruction: TransactionInstruction;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface TransactionJSON {
|
||||
recentBlockhash: string | null;
|
||||
feePayer: string | null;
|
||||
nonceInfo: {
|
||||
nonce: string;
|
||||
nonceInstruction: TransactionInstructionJSON;
|
||||
} | null;
|
||||
instructions: TransactionInstructionJSON[];
|
||||
signers: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaction class
|
||||
*/
|
||||
export class Transaction {
|
||||
/**
|
||||
* Signatures for the transaction. Typically created by invoking the
|
||||
* `sign()` method
|
||||
*/
|
||||
signatures: Array<SignaturePubkeyPair> = [];
|
||||
|
||||
/**
|
||||
* The first (payer) Transaction signature
|
||||
*
|
||||
* @returns {Buffer | null} Buffer of payer's signature
|
||||
*/
|
||||
get signature(): Buffer | null {
|
||||
if (this.signatures.length > 0) {
|
||||
return this.signatures[0].signature;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The transaction fee payer
|
||||
*/
|
||||
feePayer?: PublicKey;
|
||||
|
||||
/**
|
||||
* The instructions to atomically execute
|
||||
*/
|
||||
instructions: Array<TransactionInstruction> = [];
|
||||
|
||||
/**
|
||||
* A recent transaction id. Must be populated by the caller
|
||||
*/
|
||||
recentBlockhash?: Blockhash;
|
||||
|
||||
/**
|
||||
* the last block chain can advance to before tx is declared expired
|
||||
* */
|
||||
lastValidBlockHeight?: number;
|
||||
|
||||
/**
|
||||
* Optional Nonce information. If populated, transaction will use a durable
|
||||
* Nonce hash instead of a recentBlockhash. Must be populated by the caller
|
||||
*/
|
||||
nonceInfo?: NonceInformation;
|
||||
|
||||
/**
|
||||
* If this is a nonce transaction this represents the minimum slot from which
|
||||
* to evaluate if the nonce has advanced when attempting to confirm the
|
||||
* transaction. This protects against a case where the transaction confirmation
|
||||
* logic loads the nonce account from an old slot and assumes the mismatch in
|
||||
* nonce value implies that the nonce has been advanced.
|
||||
*/
|
||||
minNonceContextSlot?: number;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_message?: Message;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_json?: TransactionJSON;
|
||||
|
||||
// Construct a transaction with a blockhash and lastValidBlockHeight
|
||||
constructor(opts?: TransactionBlockhashCtor);
|
||||
|
||||
// Construct a transaction using a durable nonce
|
||||
constructor(opts?: TransactionNonceCtor);
|
||||
|
||||
/**
|
||||
* @deprecated `TransactionCtorFields` has been deprecated and will be removed in a future version.
|
||||
* Please supply a `TransactionBlockhashCtor` instead.
|
||||
*/
|
||||
constructor(opts?: TransactionCtorFields_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Construct an empty Transaction
|
||||
*/
|
||||
constructor(
|
||||
opts?:
|
||||
| TransactionBlockhashCtor
|
||||
| TransactionNonceCtor
|
||||
| TransactionCtorFields_DEPRECATED,
|
||||
) {
|
||||
if (!opts) {
|
||||
return;
|
||||
}
|
||||
if (opts.feePayer) {
|
||||
this.feePayer = opts.feePayer;
|
||||
}
|
||||
if (opts.signatures) {
|
||||
this.signatures = opts.signatures;
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(opts, 'nonceInfo')) {
|
||||
const {minContextSlot, nonceInfo} = opts as TransactionNonceCtor;
|
||||
this.minNonceContextSlot = minContextSlot;
|
||||
this.nonceInfo = nonceInfo;
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(opts, 'lastValidBlockHeight')
|
||||
) {
|
||||
const {blockhash, lastValidBlockHeight} =
|
||||
opts as TransactionBlockhashCtor;
|
||||
this.recentBlockhash = blockhash;
|
||||
this.lastValidBlockHeight = lastValidBlockHeight;
|
||||
} else {
|
||||
const {recentBlockhash, nonceInfo} =
|
||||
opts as TransactionCtorFields_DEPRECATED;
|
||||
if (nonceInfo) {
|
||||
this.nonceInfo = nonceInfo;
|
||||
}
|
||||
this.recentBlockhash = recentBlockhash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
toJSON(): TransactionJSON {
|
||||
return {
|
||||
recentBlockhash: this.recentBlockhash || null,
|
||||
feePayer: this.feePayer ? this.feePayer.toJSON() : null,
|
||||
nonceInfo: this.nonceInfo
|
||||
? {
|
||||
nonce: this.nonceInfo.nonce,
|
||||
nonceInstruction: this.nonceInfo.nonceInstruction.toJSON(),
|
||||
}
|
||||
: null,
|
||||
instructions: this.instructions.map(instruction => instruction.toJSON()),
|
||||
signers: this.signatures.map(({publicKey}) => {
|
||||
return publicKey.toJSON();
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one or more instructions to this Transaction
|
||||
*
|
||||
* @param {Array< Transaction | TransactionInstruction | TransactionInstructionCtorFields >} items - Instructions to add to the Transaction
|
||||
*/
|
||||
add(
|
||||
...items: Array<
|
||||
Transaction | TransactionInstruction | TransactionInstructionCtorFields
|
||||
>
|
||||
): Transaction {
|
||||
if (items.length === 0) {
|
||||
throw new Error('No instructions');
|
||||
}
|
||||
|
||||
items.forEach((item: any) => {
|
||||
if ('instructions' in item) {
|
||||
this.instructions = this.instructions.concat(item.instructions);
|
||||
} else if ('data' in item && 'programId' in item && 'keys' in item) {
|
||||
this.instructions.push(item);
|
||||
} else {
|
||||
this.instructions.push(new TransactionInstruction(item));
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile transaction data
|
||||
*/
|
||||
compileMessage(): Message {
|
||||
if (
|
||||
this._message &&
|
||||
JSON.stringify(this.toJSON()) === JSON.stringify(this._json)
|
||||
) {
|
||||
return this._message;
|
||||
}
|
||||
|
||||
let recentBlockhash;
|
||||
let instructions: TransactionInstruction[];
|
||||
if (this.nonceInfo) {
|
||||
recentBlockhash = this.nonceInfo.nonce;
|
||||
if (this.instructions[0] != this.nonceInfo.nonceInstruction) {
|
||||
instructions = [this.nonceInfo.nonceInstruction, ...this.instructions];
|
||||
} else {
|
||||
instructions = this.instructions;
|
||||
}
|
||||
} else {
|
||||
recentBlockhash = this.recentBlockhash;
|
||||
instructions = this.instructions;
|
||||
}
|
||||
if (!recentBlockhash) {
|
||||
throw new Error('Transaction recentBlockhash required');
|
||||
}
|
||||
|
||||
if (instructions.length < 1) {
|
||||
console.warn('No instructions provided');
|
||||
}
|
||||
|
||||
let feePayer: PublicKey;
|
||||
if (this.feePayer) {
|
||||
feePayer = this.feePayer;
|
||||
} else if (this.signatures.length > 0 && this.signatures[0].publicKey) {
|
||||
// Use implicit fee payer
|
||||
feePayer = this.signatures[0].publicKey;
|
||||
} else {
|
||||
throw new Error('Transaction fee payer required');
|
||||
}
|
||||
|
||||
for (let i = 0; i < instructions.length; i++) {
|
||||
if (instructions[i].programId === undefined) {
|
||||
throw new Error(
|
||||
`Transaction instruction index ${i} has undefined program id`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const programIds: string[] = [];
|
||||
const accountMetas: AccountMeta[] = [];
|
||||
instructions.forEach(instruction => {
|
||||
instruction.keys.forEach(accountMeta => {
|
||||
accountMetas.push({...accountMeta});
|
||||
});
|
||||
|
||||
const programId = instruction.programId.toString();
|
||||
if (!programIds.includes(programId)) {
|
||||
programIds.push(programId);
|
||||
}
|
||||
});
|
||||
|
||||
// Append programID account metas
|
||||
programIds.forEach(programId => {
|
||||
accountMetas.push({
|
||||
pubkey: new PublicKey(programId),
|
||||
isSigner: false,
|
||||
isWritable: false,
|
||||
});
|
||||
});
|
||||
|
||||
// Cull duplicate account metas
|
||||
const uniqueMetas: AccountMeta[] = [];
|
||||
accountMetas.forEach(accountMeta => {
|
||||
const pubkeyString = accountMeta.pubkey.toString();
|
||||
const uniqueIndex = uniqueMetas.findIndex(x => {
|
||||
return x.pubkey.toString() === pubkeyString;
|
||||
});
|
||||
if (uniqueIndex > -1) {
|
||||
uniqueMetas[uniqueIndex].isWritable =
|
||||
uniqueMetas[uniqueIndex].isWritable || accountMeta.isWritable;
|
||||
uniqueMetas[uniqueIndex].isSigner =
|
||||
uniqueMetas[uniqueIndex].isSigner || accountMeta.isSigner;
|
||||
} else {
|
||||
uniqueMetas.push(accountMeta);
|
||||
}
|
||||
});
|
||||
|
||||
// Sort. Prioritizing first by signer, then by writable
|
||||
uniqueMetas.sort(function (x, y) {
|
||||
if (x.isSigner !== y.isSigner) {
|
||||
// Signers always come before non-signers
|
||||
return x.isSigner ? -1 : 1;
|
||||
}
|
||||
if (x.isWritable !== y.isWritable) {
|
||||
// Writable accounts always come before read-only accounts
|
||||
return x.isWritable ? -1 : 1;
|
||||
}
|
||||
// Otherwise, sort by pubkey, stringwise.
|
||||
const options = {
|
||||
localeMatcher: 'best fit',
|
||||
usage: 'sort',
|
||||
sensitivity: 'variant',
|
||||
ignorePunctuation: false,
|
||||
numeric: false,
|
||||
caseFirst: 'lower',
|
||||
} as Intl.CollatorOptions;
|
||||
return x.pubkey
|
||||
.toBase58()
|
||||
.localeCompare(y.pubkey.toBase58(), 'en', options);
|
||||
});
|
||||
|
||||
// Move fee payer to the front
|
||||
const feePayerIndex = uniqueMetas.findIndex(x => {
|
||||
return x.pubkey.equals(feePayer);
|
||||
});
|
||||
if (feePayerIndex > -1) {
|
||||
const [payerMeta] = uniqueMetas.splice(feePayerIndex, 1);
|
||||
payerMeta.isSigner = true;
|
||||
payerMeta.isWritable = true;
|
||||
uniqueMetas.unshift(payerMeta);
|
||||
} else {
|
||||
uniqueMetas.unshift({
|
||||
pubkey: feePayer,
|
||||
isSigner: true,
|
||||
isWritable: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Disallow unknown signers
|
||||
for (const signature of this.signatures) {
|
||||
const uniqueIndex = uniqueMetas.findIndex(x => {
|
||||
return x.pubkey.equals(signature.publicKey);
|
||||
});
|
||||
if (uniqueIndex > -1) {
|
||||
if (!uniqueMetas[uniqueIndex].isSigner) {
|
||||
uniqueMetas[uniqueIndex].isSigner = true;
|
||||
console.warn(
|
||||
'Transaction references a signature that is unnecessary, ' +
|
||||
'only the fee payer and instruction signer accounts should sign a transaction. ' +
|
||||
'This behavior is deprecated and will throw an error in the next major version release.',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`unknown signer: ${signature.publicKey.toString()}`);
|
||||
}
|
||||
}
|
||||
|
||||
let numRequiredSignatures = 0;
|
||||
let numReadonlySignedAccounts = 0;
|
||||
let numReadonlyUnsignedAccounts = 0;
|
||||
|
||||
// Split out signing from non-signing keys and count header values
|
||||
const signedKeys: string[] = [];
|
||||
const unsignedKeys: string[] = [];
|
||||
uniqueMetas.forEach(({pubkey, isSigner, isWritable}) => {
|
||||
if (isSigner) {
|
||||
signedKeys.push(pubkey.toString());
|
||||
numRequiredSignatures += 1;
|
||||
if (!isWritable) {
|
||||
numReadonlySignedAccounts += 1;
|
||||
}
|
||||
} else {
|
||||
unsignedKeys.push(pubkey.toString());
|
||||
if (!isWritable) {
|
||||
numReadonlyUnsignedAccounts += 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const accountKeys = signedKeys.concat(unsignedKeys);
|
||||
const compiledInstructions: CompiledInstruction[] = instructions.map(
|
||||
instruction => {
|
||||
const {data, programId} = instruction;
|
||||
return {
|
||||
programIdIndex: accountKeys.indexOf(programId.toString()),
|
||||
accounts: instruction.keys.map(meta =>
|
||||
accountKeys.indexOf(meta.pubkey.toString()),
|
||||
),
|
||||
data: bs58.encode(data),
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
compiledInstructions.forEach(instruction => {
|
||||
invariant(instruction.programIdIndex >= 0);
|
||||
instruction.accounts.forEach(keyIndex => invariant(keyIndex >= 0));
|
||||
});
|
||||
|
||||
return new Message({
|
||||
header: {
|
||||
numRequiredSignatures,
|
||||
numReadonlySignedAccounts,
|
||||
numReadonlyUnsignedAccounts,
|
||||
},
|
||||
accountKeys,
|
||||
recentBlockhash,
|
||||
instructions: compiledInstructions,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_compile(): Message {
|
||||
const message = this.compileMessage();
|
||||
const signedKeys = message.accountKeys.slice(
|
||||
0,
|
||||
message.header.numRequiredSignatures,
|
||||
);
|
||||
|
||||
if (this.signatures.length === signedKeys.length) {
|
||||
const valid = this.signatures.every((pair, index) => {
|
||||
return signedKeys[index].equals(pair.publicKey);
|
||||
});
|
||||
|
||||
if (valid) return message;
|
||||
}
|
||||
|
||||
this.signatures = signedKeys.map(publicKey => ({
|
||||
signature: null,
|
||||
publicKey,
|
||||
}));
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a buffer of the Transaction data that need to be covered by signatures
|
||||
*/
|
||||
serializeMessage(): Buffer {
|
||||
return this._compile().serialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the estimated fee associated with a transaction
|
||||
*
|
||||
* @param {Connection} connection Connection to RPC Endpoint.
|
||||
*
|
||||
* @returns {Promise<number | null>} The estimated fee for the transaction
|
||||
*/
|
||||
async getEstimatedFee(connection: Connection): Promise<number | null> {
|
||||
return (await connection.getFeeForMessage(this.compileMessage())).value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the public keys which will be used to sign the Transaction.
|
||||
* The first signer will be used as the transaction fee payer account.
|
||||
*
|
||||
* Signatures can be added with either `partialSign` or `addSignature`
|
||||
*
|
||||
* @deprecated Deprecated since v0.84.0. Only the fee payer needs to be
|
||||
* specified and it can be set in the Transaction constructor or with the
|
||||
* `feePayer` property.
|
||||
*/
|
||||
setSigners(...signers: Array<PublicKey>) {
|
||||
if (signers.length === 0) {
|
||||
throw new Error('No signers');
|
||||
}
|
||||
|
||||
const seen = new Set();
|
||||
this.signatures = signers
|
||||
.filter(publicKey => {
|
||||
const key = publicKey.toString();
|
||||
if (seen.has(key)) {
|
||||
return false;
|
||||
} else {
|
||||
seen.add(key);
|
||||
return true;
|
||||
}
|
||||
})
|
||||
.map(publicKey => ({signature: null, publicKey}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the Transaction with the specified signers. Multiple signatures may
|
||||
* be applied to a Transaction. The first signature is considered "primary"
|
||||
* and is used identify and confirm transactions.
|
||||
*
|
||||
* If the Transaction `feePayer` is not set, the first signer will be used
|
||||
* as the transaction fee payer account.
|
||||
*
|
||||
* Transaction fields should not be modified after the first call to `sign`,
|
||||
* as doing so may invalidate the signature and cause the Transaction to be
|
||||
* rejected.
|
||||
*
|
||||
* The Transaction must be assigned a valid `recentBlockhash` before invoking this method
|
||||
*
|
||||
* @param {Array<Signer>} signers Array of signers that will sign the transaction
|
||||
*/
|
||||
sign(...signers: Array<Signer>) {
|
||||
if (signers.length === 0) {
|
||||
throw new Error('No signers');
|
||||
}
|
||||
|
||||
// Dedupe signers
|
||||
const seen = new Set();
|
||||
const uniqueSigners = [];
|
||||
for (const signer of signers) {
|
||||
const key = signer.publicKey.toString();
|
||||
if (seen.has(key)) {
|
||||
continue;
|
||||
} else {
|
||||
seen.add(key);
|
||||
uniqueSigners.push(signer);
|
||||
}
|
||||
}
|
||||
|
||||
this.signatures = uniqueSigners.map(signer => ({
|
||||
signature: null,
|
||||
publicKey: signer.publicKey,
|
||||
}));
|
||||
|
||||
const message = this._compile();
|
||||
this._partialSign(message, ...uniqueSigners);
|
||||
}
|
||||
|
||||
/**
|
||||
* Partially sign a transaction with the specified accounts. All accounts must
|
||||
* correspond to either the fee payer or a signer account in the transaction
|
||||
* instructions.
|
||||
*
|
||||
* All the caveats from the `sign` method apply to `partialSign`
|
||||
*
|
||||
* @param {Array<Signer>} signers Array of signers that will sign the transaction
|
||||
*/
|
||||
partialSign(...signers: Array<Signer>) {
|
||||
if (signers.length === 0) {
|
||||
throw new Error('No signers');
|
||||
}
|
||||
|
||||
// Dedupe signers
|
||||
const seen = new Set();
|
||||
const uniqueSigners = [];
|
||||
for (const signer of signers) {
|
||||
const key = signer.publicKey.toString();
|
||||
if (seen.has(key)) {
|
||||
continue;
|
||||
} else {
|
||||
seen.add(key);
|
||||
uniqueSigners.push(signer);
|
||||
}
|
||||
}
|
||||
|
||||
const message = this._compile();
|
||||
this._partialSign(message, ...uniqueSigners);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_partialSign(message: Message, ...signers: Array<Signer>) {
|
||||
const signData = message.serialize();
|
||||
signers.forEach(signer => {
|
||||
const signature = sign(signData, signer.secretKey);
|
||||
this._addSignature(signer.publicKey, toBuffer(signature));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an externally created signature to a transaction. The public key
|
||||
* must correspond to either the fee payer or a signer account in the transaction
|
||||
* instructions.
|
||||
*
|
||||
* @param {PublicKey} pubkey Public key that will be added to the transaction.
|
||||
* @param {Buffer} signature An externally created signature to add to the transaction.
|
||||
*/
|
||||
addSignature(pubkey: PublicKey, signature: Buffer) {
|
||||
this._compile(); // Ensure signatures array is populated
|
||||
this._addSignature(pubkey, signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_addSignature(pubkey: PublicKey, signature: Buffer) {
|
||||
invariant(signature.length === 64);
|
||||
|
||||
const index = this.signatures.findIndex(sigpair =>
|
||||
pubkey.equals(sigpair.publicKey),
|
||||
);
|
||||
if (index < 0) {
|
||||
throw new Error(`unknown signer: ${pubkey.toString()}`);
|
||||
}
|
||||
|
||||
this.signatures[index].signature = Buffer.from(signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify signatures of a Transaction
|
||||
* Optional parameter specifies if we're expecting a fully signed Transaction or a partially signed one.
|
||||
* If no boolean is provided, we expect a fully signed Transaction by default.
|
||||
*
|
||||
* @param {boolean} [requireAllSignatures=true] Require a fully signed Transaction
|
||||
*/
|
||||
verifySignatures(requireAllSignatures: boolean = true): boolean {
|
||||
const signatureErrors = this._getMessageSignednessErrors(
|
||||
this.serializeMessage(),
|
||||
requireAllSignatures,
|
||||
);
|
||||
return !signatureErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_getMessageSignednessErrors(
|
||||
message: Uint8Array,
|
||||
requireAllSignatures: boolean,
|
||||
): MessageSignednessErrors | undefined {
|
||||
const errors: MessageSignednessErrors = {};
|
||||
for (const {signature, publicKey} of this.signatures) {
|
||||
if (signature === null) {
|
||||
if (requireAllSignatures) {
|
||||
(errors.missing ||= []).push(publicKey);
|
||||
}
|
||||
} else {
|
||||
if (!verify(signature, message, publicKey.toBytes())) {
|
||||
(errors.invalid ||= []).push(publicKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors.invalid || errors.missing ? errors : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the Transaction in the wire format.
|
||||
*
|
||||
* @param {Buffer} [config] Config of transaction.
|
||||
*
|
||||
* @returns {Buffer} Signature of transaction in wire format.
|
||||
*/
|
||||
serialize(config?: SerializeConfig): Buffer {
|
||||
const {requireAllSignatures, verifySignatures} = Object.assign(
|
||||
{requireAllSignatures: true, verifySignatures: true},
|
||||
config,
|
||||
);
|
||||
|
||||
const signData = this.serializeMessage();
|
||||
if (verifySignatures) {
|
||||
const sigErrors = this._getMessageSignednessErrors(
|
||||
signData,
|
||||
requireAllSignatures,
|
||||
);
|
||||
if (sigErrors) {
|
||||
let errorMessage = 'Signature verification failed.';
|
||||
if (sigErrors.invalid) {
|
||||
errorMessage += `\nInvalid signature for public key${
|
||||
sigErrors.invalid.length === 1 ? '' : '(s)'
|
||||
} [\`${sigErrors.invalid.map(p => p.toBase58()).join('`, `')}\`].`;
|
||||
}
|
||||
if (sigErrors.missing) {
|
||||
errorMessage += `\nMissing signature for public key${
|
||||
sigErrors.missing.length === 1 ? '' : '(s)'
|
||||
} [\`${sigErrors.missing.map(p => p.toBase58()).join('`, `')}\`].`;
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
return this._serialize(signData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_serialize(signData: Buffer): Buffer {
|
||||
const {signatures} = this;
|
||||
const signatureCount: number[] = [];
|
||||
shortvec.encodeLength(signatureCount, signatures.length);
|
||||
const transactionLength =
|
||||
signatureCount.length + signatures.length * 64 + signData.length;
|
||||
const wireTransaction = Buffer.alloc(transactionLength);
|
||||
invariant(signatures.length < 256);
|
||||
Buffer.from(signatureCount).copy(wireTransaction, 0);
|
||||
signatures.forEach(({signature}, index) => {
|
||||
if (signature !== null) {
|
||||
invariant(signature.length === 64, `signature has invalid length`);
|
||||
Buffer.from(signature).copy(
|
||||
wireTransaction,
|
||||
signatureCount.length + index * 64,
|
||||
);
|
||||
}
|
||||
});
|
||||
signData.copy(
|
||||
wireTransaction,
|
||||
signatureCount.length + signatures.length * 64,
|
||||
);
|
||||
invariant(
|
||||
wireTransaction.length <= PACKET_DATA_SIZE,
|
||||
`Transaction too large: ${wireTransaction.length} > ${PACKET_DATA_SIZE}`,
|
||||
);
|
||||
return wireTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method
|
||||
* @internal
|
||||
*/
|
||||
get keys(): Array<PublicKey> {
|
||||
invariant(this.instructions.length === 1);
|
||||
return this.instructions[0].keys.map(keyObj => keyObj.pubkey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method
|
||||
* @internal
|
||||
*/
|
||||
get programId(): PublicKey {
|
||||
invariant(this.instructions.length === 1);
|
||||
return this.instructions[0].programId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method
|
||||
* @internal
|
||||
*/
|
||||
get data(): Buffer {
|
||||
invariant(this.instructions.length === 1);
|
||||
return this.instructions[0].data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a wire transaction into a Transaction object.
|
||||
*
|
||||
* @param {Buffer | Uint8Array | Array<number>} buffer Signature of wire Transaction
|
||||
*
|
||||
* @returns {Transaction} Transaction associated with the signature
|
||||
*/
|
||||
static from(buffer: Buffer | Uint8Array | Array<number>): Transaction {
|
||||
// Slice up wire data
|
||||
let byteArray = [...buffer];
|
||||
|
||||
const signatureCount = shortvec.decodeLength(byteArray);
|
||||
let signatures = [];
|
||||
for (let i = 0; i < signatureCount; i++) {
|
||||
const signature = guardedSplice(byteArray, 0, SIGNATURE_LENGTH_IN_BYTES);
|
||||
signatures.push(bs58.encode(Buffer.from(signature)));
|
||||
}
|
||||
|
||||
return Transaction.populate(Message.from(byteArray), signatures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate Transaction object from message and signatures
|
||||
*
|
||||
* @param {Message} message Message of transaction
|
||||
* @param {Array<string>} signatures List of signatures to assign to the transaction
|
||||
*
|
||||
* @returns {Transaction} The populated Transaction
|
||||
*/
|
||||
static populate(
|
||||
message: Message,
|
||||
signatures: Array<string> = [],
|
||||
): Transaction {
|
||||
const transaction = new Transaction();
|
||||
transaction.recentBlockhash = message.recentBlockhash;
|
||||
if (message.header.numRequiredSignatures > 0) {
|
||||
transaction.feePayer = message.accountKeys[0];
|
||||
}
|
||||
signatures.forEach((signature, index) => {
|
||||
const sigPubkeyPair = {
|
||||
signature:
|
||||
signature == bs58.encode(DEFAULT_SIGNATURE)
|
||||
? null
|
||||
: bs58.decode(signature),
|
||||
publicKey: message.accountKeys[index],
|
||||
};
|
||||
transaction.signatures.push(sigPubkeyPair);
|
||||
});
|
||||
|
||||
message.instructions.forEach(instruction => {
|
||||
const keys = instruction.accounts.map(account => {
|
||||
const pubkey = message.accountKeys[account];
|
||||
return {
|
||||
pubkey,
|
||||
isSigner:
|
||||
transaction.signatures.some(
|
||||
keyObj => keyObj.publicKey.toString() === pubkey.toString(),
|
||||
) || message.isAccountSigner(account),
|
||||
isWritable: message.isAccountWritable(account),
|
||||
};
|
||||
});
|
||||
|
||||
transaction.instructions.push(
|
||||
new TransactionInstruction({
|
||||
keys,
|
||||
programId: message.accountKeys[instruction.programIdIndex],
|
||||
data: bs58.decode(instruction.data),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
transaction._message = message;
|
||||
transaction._json = transaction.toJSON();
|
||||
|
||||
return transaction;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { TSESLint } from '@typescript-eslint/utils';
|
||||
declare const _default: TSESLint.RuleModule<"mismatchedCase" | "mismatchedCondition" | "replaceValueWithEnum", [], import("../../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,187 @@
|
||||
declare module "safe-buffer" {
|
||||
export class Buffer {
|
||||
length: number
|
||||
write(string: string, offset?: number, length?: number, encoding?: string): number;
|
||||
toString(encoding?: string, start?: number, end?: number): string;
|
||||
toJSON(): { type: 'Buffer', data: any[] };
|
||||
equals(otherBuffer: Buffer): boolean;
|
||||
compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
|
||||
copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
|
||||
slice(start?: number, end?: number): Buffer;
|
||||
writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUInt8(offset: number, noAssert?: boolean): number;
|
||||
readUInt16LE(offset: number, noAssert?: boolean): number;
|
||||
readUInt16BE(offset: number, noAssert?: boolean): number;
|
||||
readUInt32LE(offset: number, noAssert?: boolean): number;
|
||||
readUInt32BE(offset: number, noAssert?: boolean): number;
|
||||
readInt8(offset: number, noAssert?: boolean): number;
|
||||
readInt16LE(offset: number, noAssert?: boolean): number;
|
||||
readInt16BE(offset: number, noAssert?: boolean): number;
|
||||
readInt32LE(offset: number, noAssert?: boolean): number;
|
||||
readInt32BE(offset: number, noAssert?: boolean): number;
|
||||
readFloatLE(offset: number, noAssert?: boolean): number;
|
||||
readFloatBE(offset: number, noAssert?: boolean): number;
|
||||
readDoubleLE(offset: number, noAssert?: boolean): number;
|
||||
readDoubleBE(offset: number, noAssert?: boolean): number;
|
||||
swap16(): Buffer;
|
||||
swap32(): Buffer;
|
||||
swap64(): Buffer;
|
||||
writeUInt8(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt8(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt16LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt16BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt32LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt32BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeFloatLE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeFloatBE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;
|
||||
fill(value: any, offset?: number, end?: number): this;
|
||||
indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
|
||||
lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
|
||||
includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;
|
||||
|
||||
/**
|
||||
* Allocates a new buffer containing the given {str}.
|
||||
*
|
||||
* @param str String to store in buffer.
|
||||
* @param encoding encoding to use, optional. Default is 'utf8'
|
||||
*/
|
||||
constructor (str: string, encoding?: string);
|
||||
/**
|
||||
* Allocates a new buffer of {size} octets.
|
||||
*
|
||||
* @param size count of octets to allocate.
|
||||
*/
|
||||
constructor (size: number);
|
||||
/**
|
||||
* Allocates a new buffer containing the given {array} of octets.
|
||||
*
|
||||
* @param array The octets to store.
|
||||
*/
|
||||
constructor (array: Uint8Array);
|
||||
/**
|
||||
* Produces a Buffer backed by the same allocated memory as
|
||||
* the given {ArrayBuffer}.
|
||||
*
|
||||
*
|
||||
* @param arrayBuffer The ArrayBuffer with which to share memory.
|
||||
*/
|
||||
constructor (arrayBuffer: ArrayBuffer);
|
||||
/**
|
||||
* Allocates a new buffer containing the given {array} of octets.
|
||||
*
|
||||
* @param array The octets to store.
|
||||
*/
|
||||
constructor (array: any[]);
|
||||
/**
|
||||
* Copies the passed {buffer} data onto a new {Buffer} instance.
|
||||
*
|
||||
* @param buffer The buffer to copy.
|
||||
*/
|
||||
constructor (buffer: Buffer);
|
||||
prototype: Buffer;
|
||||
/**
|
||||
* Allocates a new Buffer using an {array} of octets.
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
static from(array: any[]): Buffer;
|
||||
/**
|
||||
* When passed a reference to the .buffer property of a TypedArray instance,
|
||||
* the newly created Buffer will share the same allocated memory as the TypedArray.
|
||||
* The optional {byteOffset} and {length} arguments specify a memory range
|
||||
* within the {arrayBuffer} that will be shared by the Buffer.
|
||||
*
|
||||
* @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()
|
||||
* @param byteOffset
|
||||
* @param length
|
||||
*/
|
||||
static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
|
||||
/**
|
||||
* Copies the passed {buffer} data onto a new Buffer instance.
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
static from(buffer: Buffer): Buffer;
|
||||
/**
|
||||
* Creates a new Buffer containing the given JavaScript string {str}.
|
||||
* If provided, the {encoding} parameter identifies the character encoding.
|
||||
* If not provided, {encoding} defaults to 'utf8'.
|
||||
*
|
||||
* @param str
|
||||
*/
|
||||
static from(str: string, encoding?: string): Buffer;
|
||||
/**
|
||||
* Returns true if {obj} is a Buffer
|
||||
*
|
||||
* @param obj object to test.
|
||||
*/
|
||||
static isBuffer(obj: any): obj is Buffer;
|
||||
/**
|
||||
* Returns true if {encoding} is a valid encoding argument.
|
||||
* Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'
|
||||
*
|
||||
* @param encoding string to test.
|
||||
*/
|
||||
static isEncoding(encoding: string): boolean;
|
||||
/**
|
||||
* Gives the actual byte length of a string. encoding defaults to 'utf8'.
|
||||
* This is not the same as String.prototype.length since that returns the number of characters in a string.
|
||||
*
|
||||
* @param string string to test.
|
||||
* @param encoding encoding used to evaluate (defaults to 'utf8')
|
||||
*/
|
||||
static byteLength(string: string, encoding?: string): number;
|
||||
/**
|
||||
* Returns a buffer which is the result of concatenating all the buffers in the list together.
|
||||
*
|
||||
* If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.
|
||||
* If the list has exactly one item, then the first item of the list is returned.
|
||||
* If the list has more than one item, then a new Buffer is created.
|
||||
*
|
||||
* @param list An array of Buffer objects to concatenate
|
||||
* @param totalLength Total length of the buffers when concatenated.
|
||||
* If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.
|
||||
*/
|
||||
static concat(list: Buffer[], totalLength?: number): Buffer;
|
||||
/**
|
||||
* The same as buf1.compare(buf2).
|
||||
*/
|
||||
static compare(buf1: Buffer, buf2: Buffer): number;
|
||||
/**
|
||||
* Allocates a new buffer of {size} octets.
|
||||
*
|
||||
* @param size count of octets to allocate.
|
||||
* @param fill if specified, buffer will be initialized by calling buf.fill(fill).
|
||||
* If parameter is omitted, buffer will be filled with zeros.
|
||||
* @param encoding encoding used for call to buf.fill while initalizing
|
||||
*/
|
||||
static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;
|
||||
/**
|
||||
* Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents
|
||||
* of the newly created Buffer are unknown and may contain sensitive data.
|
||||
*
|
||||
* @param size count of octets to allocate
|
||||
*/
|
||||
static allocUnsafe(size: number): Buffer;
|
||||
/**
|
||||
* Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents
|
||||
* of the newly created Buffer are unknown and may contain sensitive data.
|
||||
*
|
||||
* @param size count of octets to allocate
|
||||
*/
|
||||
static allocUnsafeSlow(size: number): Buffer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_throw.cjs",
|
||||
"module": "../../esm/_throw.js"
|
||||
}
|
||||
@@ -0,0 +1,570 @@
|
||||
import { createRequire } from "module";
|
||||
import { basename, dirname, normalize, relative, resolve, sep } from "path";
|
||||
import * as nativeFs from "fs";
|
||||
|
||||
//#region rolldown:runtime
|
||||
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
||||
|
||||
//#endregion
|
||||
//#region src/utils.ts
|
||||
function cleanPath(path) {
|
||||
let normalized = normalize(path);
|
||||
if (normalized.length > 1 && normalized[normalized.length - 1] === sep) normalized = normalized.substring(0, normalized.length - 1);
|
||||
return normalized;
|
||||
}
|
||||
const SLASHES_REGEX = /[\\/]/g;
|
||||
function convertSlashes(path, separator) {
|
||||
return path.replace(SLASHES_REGEX, separator);
|
||||
}
|
||||
const WINDOWS_ROOT_DIR_REGEX = /^[a-z]:[\\/]$/i;
|
||||
function isRootDirectory(path) {
|
||||
return path === "/" || WINDOWS_ROOT_DIR_REGEX.test(path);
|
||||
}
|
||||
function normalizePath(path, options) {
|
||||
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
|
||||
const pathNeedsCleaning = process.platform === "win32" && path.includes("/") || path.startsWith(".");
|
||||
if (resolvePaths) path = resolve(path);
|
||||
if (normalizePath$1 || pathNeedsCleaning) path = cleanPath(path);
|
||||
if (path === ".") return "";
|
||||
const needsSeperator = path[path.length - 1] !== pathSeparator;
|
||||
return convertSlashes(needsSeperator ? path + pathSeparator : path, pathSeparator);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/functions/join-path.ts
|
||||
function joinPathWithBasePath(filename, directoryPath) {
|
||||
return directoryPath + filename;
|
||||
}
|
||||
function joinPathWithRelativePath(root, options) {
|
||||
return function(filename, directoryPath) {
|
||||
const sameRoot = directoryPath.startsWith(root);
|
||||
if (sameRoot) return directoryPath.slice(root.length) + filename;
|
||||
else return convertSlashes(relative(root, directoryPath), options.pathSeparator) + options.pathSeparator + filename;
|
||||
};
|
||||
}
|
||||
function joinPath(filename) {
|
||||
return filename;
|
||||
}
|
||||
function joinDirectoryPath(filename, directoryPath, separator) {
|
||||
return directoryPath + filename + separator;
|
||||
}
|
||||
function build$7(root, options) {
|
||||
const { relativePaths, includeBasePath } = options;
|
||||
return relativePaths && root ? joinPathWithRelativePath(root, options) : includeBasePath ? joinPathWithBasePath : joinPath;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/functions/push-directory.ts
|
||||
function pushDirectoryWithRelativePath(root) {
|
||||
return function(directoryPath, paths) {
|
||||
paths.push(directoryPath.substring(root.length) || ".");
|
||||
};
|
||||
}
|
||||
function pushDirectoryFilterWithRelativePath(root) {
|
||||
return function(directoryPath, paths, filters) {
|
||||
const relativePath = directoryPath.substring(root.length) || ".";
|
||||
if (filters.every((filter) => filter(relativePath, true))) paths.push(relativePath);
|
||||
};
|
||||
}
|
||||
const pushDirectory = (directoryPath, paths) => {
|
||||
paths.push(directoryPath || ".");
|
||||
};
|
||||
const pushDirectoryFilter = (directoryPath, paths, filters) => {
|
||||
const path = directoryPath || ".";
|
||||
if (filters.every((filter) => filter(path, true))) paths.push(path);
|
||||
};
|
||||
const empty$2 = () => {};
|
||||
function build$6(root, options) {
|
||||
const { includeDirs, filters, relativePaths } = options;
|
||||
if (!includeDirs) return empty$2;
|
||||
if (relativePaths) return filters && filters.length ? pushDirectoryFilterWithRelativePath(root) : pushDirectoryWithRelativePath(root);
|
||||
return filters && filters.length ? pushDirectoryFilter : pushDirectory;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/functions/push-file.ts
|
||||
const pushFileFilterAndCount = (filename, _paths, counts, filters) => {
|
||||
if (filters.every((filter) => filter(filename, false))) counts.files++;
|
||||
};
|
||||
const pushFileFilter = (filename, paths, _counts, filters) => {
|
||||
if (filters.every((filter) => filter(filename, false))) paths.push(filename);
|
||||
};
|
||||
const pushFileCount = (_filename, _paths, counts, _filters) => {
|
||||
counts.files++;
|
||||
};
|
||||
const pushFile = (filename, paths) => {
|
||||
paths.push(filename);
|
||||
};
|
||||
const empty$1 = () => {};
|
||||
function build$5(options) {
|
||||
const { excludeFiles, filters, onlyCounts } = options;
|
||||
if (excludeFiles) return empty$1;
|
||||
if (filters && filters.length) return onlyCounts ? pushFileFilterAndCount : pushFileFilter;
|
||||
else if (onlyCounts) return pushFileCount;
|
||||
else return pushFile;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/functions/get-array.ts
|
||||
const getArray = (paths) => {
|
||||
return paths;
|
||||
};
|
||||
const getArrayGroup = () => {
|
||||
return [""].slice(0, 0);
|
||||
};
|
||||
function build$4(options) {
|
||||
return options.group ? getArrayGroup : getArray;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/functions/group-files.ts
|
||||
const groupFiles = (groups, directory, files) => {
|
||||
groups.push({
|
||||
directory,
|
||||
files,
|
||||
dir: directory
|
||||
});
|
||||
};
|
||||
const empty = () => {};
|
||||
function build$3(options) {
|
||||
return options.group ? groupFiles : empty;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/functions/resolve-symlink.ts
|
||||
const resolveSymlinksAsync = function(path, state, callback$1) {
|
||||
const { queue, fs, options: { suppressErrors } } = state;
|
||||
queue.enqueue();
|
||||
fs.realpath(path, (error, resolvedPath) => {
|
||||
if (error) return queue.dequeue(suppressErrors ? null : error, state);
|
||||
fs.stat(resolvedPath, (error$1, stat) => {
|
||||
if (error$1) return queue.dequeue(suppressErrors ? null : error$1, state);
|
||||
if (stat.isDirectory() && isRecursive(path, resolvedPath, state)) return queue.dequeue(null, state);
|
||||
callback$1(stat, resolvedPath);
|
||||
queue.dequeue(null, state);
|
||||
});
|
||||
});
|
||||
};
|
||||
const resolveSymlinks = function(path, state, callback$1) {
|
||||
const { queue, fs, options: { suppressErrors } } = state;
|
||||
queue.enqueue();
|
||||
try {
|
||||
const resolvedPath = fs.realpathSync(path);
|
||||
const stat = fs.statSync(resolvedPath);
|
||||
if (stat.isDirectory() && isRecursive(path, resolvedPath, state)) return;
|
||||
callback$1(stat, resolvedPath);
|
||||
} catch (e) {
|
||||
if (!suppressErrors) throw e;
|
||||
}
|
||||
};
|
||||
function build$2(options, isSynchronous) {
|
||||
if (!options.resolveSymlinks || options.excludeSymlinks) return null;
|
||||
return isSynchronous ? resolveSymlinks : resolveSymlinksAsync;
|
||||
}
|
||||
function isRecursive(path, resolved, state) {
|
||||
if (state.options.useRealPaths) return isRecursiveUsingRealPaths(resolved, state);
|
||||
let parent = dirname(path);
|
||||
let depth = 1;
|
||||
while (parent !== state.root && depth < 2) {
|
||||
const resolvedPath = state.symlinks.get(parent);
|
||||
const isSameRoot = !!resolvedPath && (resolvedPath === resolved || resolvedPath.startsWith(resolved) || resolved.startsWith(resolvedPath));
|
||||
if (isSameRoot) depth++;
|
||||
else parent = dirname(parent);
|
||||
}
|
||||
state.symlinks.set(path, resolved);
|
||||
return depth > 1;
|
||||
}
|
||||
function isRecursiveUsingRealPaths(resolved, state) {
|
||||
return state.visited.includes(resolved + state.options.pathSeparator);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/functions/invoke-callback.ts
|
||||
const onlyCountsSync = (state) => {
|
||||
return state.counts;
|
||||
};
|
||||
const groupsSync = (state) => {
|
||||
return state.groups;
|
||||
};
|
||||
const defaultSync = (state) => {
|
||||
return state.paths;
|
||||
};
|
||||
const limitFilesSync = (state) => {
|
||||
return state.paths.slice(0, state.options.maxFiles);
|
||||
};
|
||||
const onlyCountsAsync = (state, error, callback$1) => {
|
||||
report(error, callback$1, state.counts, state.options.suppressErrors);
|
||||
return null;
|
||||
};
|
||||
const defaultAsync = (state, error, callback$1) => {
|
||||
report(error, callback$1, state.paths, state.options.suppressErrors);
|
||||
return null;
|
||||
};
|
||||
const limitFilesAsync = (state, error, callback$1) => {
|
||||
report(error, callback$1, state.paths.slice(0, state.options.maxFiles), state.options.suppressErrors);
|
||||
return null;
|
||||
};
|
||||
const groupsAsync = (state, error, callback$1) => {
|
||||
report(error, callback$1, state.groups, state.options.suppressErrors);
|
||||
return null;
|
||||
};
|
||||
function report(error, callback$1, output, suppressErrors) {
|
||||
if (error && !suppressErrors) callback$1(error, output);
|
||||
else callback$1(null, output);
|
||||
}
|
||||
function build$1(options, isSynchronous) {
|
||||
const { onlyCounts, group, maxFiles } = options;
|
||||
if (onlyCounts) return isSynchronous ? onlyCountsSync : onlyCountsAsync;
|
||||
else if (group) return isSynchronous ? groupsSync : groupsAsync;
|
||||
else if (maxFiles) return isSynchronous ? limitFilesSync : limitFilesAsync;
|
||||
else return isSynchronous ? defaultSync : defaultAsync;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/functions/walk-directory.ts
|
||||
const readdirOpts = { withFileTypes: true };
|
||||
const walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
||||
state.queue.enqueue();
|
||||
if (currentDepth < 0) return state.queue.dequeue(null, state);
|
||||
const { fs } = state;
|
||||
state.visited.push(crawlPath);
|
||||
state.counts.directories++;
|
||||
fs.readdir(crawlPath || ".", readdirOpts, (error, entries = []) => {
|
||||
callback$1(entries, directoryPath, currentDepth);
|
||||
state.queue.dequeue(state.options.suppressErrors ? null : error, state);
|
||||
});
|
||||
};
|
||||
const walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
||||
const { fs } = state;
|
||||
if (currentDepth < 0) return;
|
||||
state.visited.push(crawlPath);
|
||||
state.counts.directories++;
|
||||
let entries = [];
|
||||
try {
|
||||
entries = fs.readdirSync(crawlPath || ".", readdirOpts);
|
||||
} catch (e) {
|
||||
if (!state.options.suppressErrors) throw e;
|
||||
}
|
||||
callback$1(entries, directoryPath, currentDepth);
|
||||
};
|
||||
function build(isSynchronous) {
|
||||
return isSynchronous ? walkSync : walkAsync;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/queue.ts
|
||||
/**
|
||||
* This is a custom stateless queue to track concurrent async fs calls.
|
||||
* It increments a counter whenever a call is queued and decrements it
|
||||
* as soon as it completes. When the counter hits 0, it calls onQueueEmpty.
|
||||
*/
|
||||
var Queue = class {
|
||||
count = 0;
|
||||
constructor(onQueueEmpty) {
|
||||
this.onQueueEmpty = onQueueEmpty;
|
||||
}
|
||||
enqueue() {
|
||||
this.count++;
|
||||
return this.count;
|
||||
}
|
||||
dequeue(error, output) {
|
||||
if (this.onQueueEmpty && (--this.count <= 0 || error)) {
|
||||
this.onQueueEmpty(error, output);
|
||||
if (error) {
|
||||
output.controller.abort();
|
||||
this.onQueueEmpty = void 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
//#region src/api/counter.ts
|
||||
var Counter = class {
|
||||
_files = 0;
|
||||
_directories = 0;
|
||||
set files(num) {
|
||||
this._files = num;
|
||||
}
|
||||
get files() {
|
||||
return this._files;
|
||||
}
|
||||
set directories(num) {
|
||||
this._directories = num;
|
||||
}
|
||||
get directories() {
|
||||
return this._directories;
|
||||
}
|
||||
/**
|
||||
* @deprecated use `directories` instead
|
||||
*/
|
||||
/* c8 ignore next 3 */
|
||||
get dirs() {
|
||||
return this._directories;
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
//#region src/api/aborter.ts
|
||||
/**
|
||||
* AbortController is not supported on Node 14 so we use this until we can drop
|
||||
* support for Node 14.
|
||||
*/
|
||||
var Aborter = class {
|
||||
aborted = false;
|
||||
abort() {
|
||||
this.aborted = true;
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
//#region src/api/walker.ts
|
||||
var Walker = class {
|
||||
root;
|
||||
isSynchronous;
|
||||
state;
|
||||
joinPath;
|
||||
pushDirectory;
|
||||
pushFile;
|
||||
getArray;
|
||||
groupFiles;
|
||||
resolveSymlink;
|
||||
walkDirectory;
|
||||
callbackInvoker;
|
||||
constructor(root, options, callback$1) {
|
||||
this.isSynchronous = !callback$1;
|
||||
this.callbackInvoker = build$1(options, this.isSynchronous);
|
||||
this.root = normalizePath(root, options);
|
||||
this.state = {
|
||||
root: isRootDirectory(this.root) ? this.root : this.root.slice(0, -1),
|
||||
paths: [""].slice(0, 0),
|
||||
groups: [],
|
||||
counts: new Counter(),
|
||||
options,
|
||||
queue: new Queue((error, state) => this.callbackInvoker(state, error, callback$1)),
|
||||
symlinks: /* @__PURE__ */ new Map(),
|
||||
visited: [""].slice(0, 0),
|
||||
controller: new Aborter(),
|
||||
fs: options.fs || nativeFs
|
||||
};
|
||||
this.joinPath = build$7(this.root, options);
|
||||
this.pushDirectory = build$6(this.root, options);
|
||||
this.pushFile = build$5(options);
|
||||
this.getArray = build$4(options);
|
||||
this.groupFiles = build$3(options);
|
||||
this.resolveSymlink = build$2(options, this.isSynchronous);
|
||||
this.walkDirectory = build(this.isSynchronous);
|
||||
}
|
||||
start() {
|
||||
this.pushDirectory(this.root, this.state.paths, this.state.options.filters);
|
||||
this.walkDirectory(this.state, this.root, this.root, this.state.options.maxDepth, this.walk);
|
||||
return this.isSynchronous ? this.callbackInvoker(this.state, null) : null;
|
||||
}
|
||||
walk = (entries, directoryPath, depth) => {
|
||||
const { paths, options: { filters, resolveSymlinks: resolveSymlinks$1, excludeSymlinks, exclude, maxFiles, signal, useRealPaths, pathSeparator }, controller } = this.state;
|
||||
if (controller.aborted || signal && signal.aborted || maxFiles && paths.length > maxFiles) return;
|
||||
const files = this.getArray(this.state.paths);
|
||||
for (let i = 0; i < entries.length; ++i) {
|
||||
const entry = entries[i];
|
||||
if (entry.isFile() || entry.isSymbolicLink() && !resolveSymlinks$1 && !excludeSymlinks) {
|
||||
const filename = this.joinPath(entry.name, directoryPath);
|
||||
this.pushFile(filename, files, this.state.counts, filters);
|
||||
} else if (entry.isDirectory()) {
|
||||
let path = joinDirectoryPath(entry.name, directoryPath, this.state.options.pathSeparator);
|
||||
if (exclude && exclude(entry.name, path)) continue;
|
||||
this.pushDirectory(path, paths, filters);
|
||||
this.walkDirectory(this.state, path, path, depth - 1, this.walk);
|
||||
} else if (this.resolveSymlink && entry.isSymbolicLink()) {
|
||||
let path = joinPathWithBasePath(entry.name, directoryPath);
|
||||
this.resolveSymlink(path, this.state, (stat, resolvedPath) => {
|
||||
if (stat.isDirectory()) {
|
||||
resolvedPath = normalizePath(resolvedPath, this.state.options);
|
||||
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path + pathSeparator)) return;
|
||||
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath : path + pathSeparator, depth - 1, this.walk);
|
||||
} else {
|
||||
resolvedPath = useRealPaths ? resolvedPath : path;
|
||||
const filename = basename(resolvedPath);
|
||||
const directoryPath$1 = normalizePath(dirname(resolvedPath), this.state.options);
|
||||
resolvedPath = this.joinPath(filename, directoryPath$1);
|
||||
this.pushFile(resolvedPath, files, this.state.counts, filters);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
this.groupFiles(this.state.groups, directoryPath, files);
|
||||
};
|
||||
};
|
||||
|
||||
//#endregion
|
||||
//#region src/api/async.ts
|
||||
function promise(root, options) {
|
||||
return new Promise((resolve$1, reject) => {
|
||||
callback(root, options, (err, output) => {
|
||||
if (err) return reject(err);
|
||||
resolve$1(output);
|
||||
});
|
||||
});
|
||||
}
|
||||
function callback(root, options, callback$1) {
|
||||
let walker = new Walker(root, options, callback$1);
|
||||
walker.start();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/api/sync.ts
|
||||
function sync(root, options) {
|
||||
const walker = new Walker(root, options);
|
||||
return walker.start();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/builder/api-builder.ts
|
||||
var APIBuilder = class {
|
||||
constructor(root, options) {
|
||||
this.root = root;
|
||||
this.options = options;
|
||||
}
|
||||
withPromise() {
|
||||
return promise(this.root, this.options);
|
||||
}
|
||||
withCallback(cb) {
|
||||
callback(this.root, this.options, cb);
|
||||
}
|
||||
sync() {
|
||||
return sync(this.root, this.options);
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
//#region src/builder/index.ts
|
||||
let pm = null;
|
||||
/* c8 ignore next 6 */
|
||||
try {
|
||||
__require.resolve("picomatch");
|
||||
pm = __require("picomatch");
|
||||
} catch {}
|
||||
var Builder = class {
|
||||
globCache = {};
|
||||
options = {
|
||||
maxDepth: Infinity,
|
||||
suppressErrors: true,
|
||||
pathSeparator: sep,
|
||||
filters: []
|
||||
};
|
||||
globFunction;
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...this.options,
|
||||
...options
|
||||
};
|
||||
this.globFunction = this.options.globFunction;
|
||||
}
|
||||
group() {
|
||||
this.options.group = true;
|
||||
return this;
|
||||
}
|
||||
withPathSeparator(separator) {
|
||||
this.options.pathSeparator = separator;
|
||||
return this;
|
||||
}
|
||||
withBasePath() {
|
||||
this.options.includeBasePath = true;
|
||||
return this;
|
||||
}
|
||||
withRelativePaths() {
|
||||
this.options.relativePaths = true;
|
||||
return this;
|
||||
}
|
||||
withDirs() {
|
||||
this.options.includeDirs = true;
|
||||
return this;
|
||||
}
|
||||
withMaxDepth(depth) {
|
||||
this.options.maxDepth = depth;
|
||||
return this;
|
||||
}
|
||||
withMaxFiles(limit) {
|
||||
this.options.maxFiles = limit;
|
||||
return this;
|
||||
}
|
||||
withFullPaths() {
|
||||
this.options.resolvePaths = true;
|
||||
this.options.includeBasePath = true;
|
||||
return this;
|
||||
}
|
||||
withErrors() {
|
||||
this.options.suppressErrors = false;
|
||||
return this;
|
||||
}
|
||||
withSymlinks({ resolvePaths = true } = {}) {
|
||||
this.options.resolveSymlinks = true;
|
||||
this.options.useRealPaths = resolvePaths;
|
||||
return this.withFullPaths();
|
||||
}
|
||||
withAbortSignal(signal) {
|
||||
this.options.signal = signal;
|
||||
return this;
|
||||
}
|
||||
normalize() {
|
||||
this.options.normalizePath = true;
|
||||
return this;
|
||||
}
|
||||
filter(predicate) {
|
||||
this.options.filters.push(predicate);
|
||||
return this;
|
||||
}
|
||||
onlyDirs() {
|
||||
this.options.excludeFiles = true;
|
||||
this.options.includeDirs = true;
|
||||
return this;
|
||||
}
|
||||
exclude(predicate) {
|
||||
this.options.exclude = predicate;
|
||||
return this;
|
||||
}
|
||||
onlyCounts() {
|
||||
this.options.onlyCounts = true;
|
||||
return this;
|
||||
}
|
||||
crawl(root) {
|
||||
return new APIBuilder(root || ".", this.options);
|
||||
}
|
||||
withGlobFunction(fn) {
|
||||
this.globFunction = fn;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* @deprecated Pass options using the constructor instead:
|
||||
* ```ts
|
||||
* new fdir(options).crawl("/path/to/root");
|
||||
* ```
|
||||
* This method will be removed in v7.0
|
||||
*/
|
||||
/* c8 ignore next 4 */
|
||||
crawlWithOptions(root, options) {
|
||||
this.options = {
|
||||
...this.options,
|
||||
...options
|
||||
};
|
||||
return new APIBuilder(root || ".", this.options);
|
||||
}
|
||||
glob(...patterns) {
|
||||
if (this.globFunction) return this.globWithOptions(patterns);
|
||||
return this.globWithOptions(patterns, ...[{ dot: true }]);
|
||||
}
|
||||
globWithOptions(patterns, ...options) {
|
||||
const globFn = this.globFunction || pm;
|
||||
/* c8 ignore next 5 */
|
||||
if (!globFn) throw new Error("Please specify a glob function to use glob matching.");
|
||||
var isMatch = this.globCache[patterns.join("\0")];
|
||||
if (!isMatch) {
|
||||
isMatch = globFn(patterns, ...options);
|
||||
this.globCache[patterns.join("\0")] = isMatch;
|
||||
}
|
||||
this.options.filters.push((path) => isMatch(path));
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { Builder as fdir };
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
let { urlAlphabet } = require('./url-alphabet/index.cjs')
|
||||
|
||||
let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))
|
||||
|
||||
let customRandom = (alphabet, defaultSize, getRandom) => {
|
||||
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
|
||||
|
||||
|
||||
|
||||
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
|
||||
|
||||
return (size = defaultSize) => {
|
||||
if (size <= 0) return ''
|
||||
let id = ''
|
||||
while (true) {
|
||||
let bytes = getRandom(step)
|
||||
let j = step | 0
|
||||
while (j--) {
|
||||
id += alphabet[bytes[j] & mask] || ''
|
||||
if (id.length === size) return id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let customAlphabet = (alphabet, size = 21) =>
|
||||
customRandom(alphabet, size, random)
|
||||
|
||||
let nanoid = (size = 21) =>
|
||||
crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
|
||||
byte &= 63
|
||||
if (byte < 36) {
|
||||
id += byte.toString(36)
|
||||
} else if (byte < 62) {
|
||||
id += (byte - 26).toString(36).toUpperCase()
|
||||
} else if (byte > 62) {
|
||||
id += '-'
|
||||
} else {
|
||||
id += '_'
|
||||
}
|
||||
return id
|
||||
}, '')
|
||||
|
||||
module.exports = { nanoid, customAlphabet, customRandom, urlAlphabet, random }
|
||||
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.version = void 0;
|
||||
// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
||||
exports.version = require('../package.json').version;
|
||||
@@ -0,0 +1,4 @@
|
||||
function _nonIterableRest() {
|
||||
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
||||
}
|
||||
export { _nonIterableRest as default };
|
||||
@@ -0,0 +1,24 @@
|
||||
"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.esnext_full = void 0;
|
||||
const dom_1 = require("./dom");
|
||||
const dom_asynciterable_1 = require("./dom.asynciterable");
|
||||
const dom_iterable_1 = require("./dom.iterable");
|
||||
const esnext_1 = require("./esnext");
|
||||
const scripthost_1 = require("./scripthost");
|
||||
const webworker_importscripts_1 = require("./webworker.importscripts");
|
||||
exports.esnext_full = {
|
||||
libs: [
|
||||
esnext_1.esnext,
|
||||
dom_1.dom,
|
||||
webworker_importscripts_1.webworker_importscripts,
|
||||
scripthost_1.scripthost,
|
||||
dom_iterable_1.dom_iterable,
|
||||
dom_asynciterable_1.dom_asynciterable,
|
||||
],
|
||||
variables: [],
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"buffer-writer.js","sourceRoot":"","sources":["../src/buffer-writer.ts"],"names":[],"mappings":";AAAA,uFAAuF;;;AAEvF,MAAa,MAAM;IAIjB,YAAoB,OAAO,GAAG;QAAV,SAAI,GAAJ,IAAI,CAAM;QAFtB,WAAM,GAAW,CAAC,CAAA;QAClB,mBAAc,GAAW,CAAC,CAAA;QAEhC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC;IAEO,MAAM,CAAC,IAAY;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAClD,IAAI,SAAS,GAAG,IAAI,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAA;YAC7B,4CAA4C;YAC5C,qEAAqE;YACrE,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA;YACjE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;YACzC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;IAEM,QAAQ,CAAC,GAAW;QACzB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;QAChD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;QAChD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QAC/C,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,QAAQ,CAAC,GAAW;QACzB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QAC/C,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,UAAU,CAAC,MAAc;QAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAChB,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;YACrC,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA,CAAC,yBAAyB;YAC9C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAC/C,IAAI,CAAC,MAAM,IAAI,GAAG,CAAA;QACpB,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAA,CAAC,kBAAkB;QACjD,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,SAAS,CAAC,SAAiB,EAAE;QAClC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACtC,IAAI,CAAC,MAAM,IAAI,GAAG,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,+EAA+E;IAC/E,8EAA8E;IAC9E,4EAA4E;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,+DAA+D;IACxD,sBAAsB,CAAC,MAAc;QAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QACrC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QACxB,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;QACtC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;QACtC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QACrC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QACrC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,GAAG,GAAG,CAAA;QAC1B,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,GAAG,CAAC,WAAmB;QAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAC/B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1C,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM,CAAA;QACjC,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,IAAI,CAAC,IAAa;QACxB,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,IAAI,CAAA;YACvC,oDAAoD;YACpD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAA;YACtD,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAA;QAC3D,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACrD,CAAC;IAEM,KAAK,CAAC,IAAa;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,cAAc,GAAG,CAAC,CAAA;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3C,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,cAAc,GAAG,CAAC,CAAA;IACzB,CAAC;CACF;AA3GD,wBA2GC"}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { SCHEMES } from "../uri";
|
||||
const NID$ = "(?:[0-9A-Za-z][0-9A-Za-z\\-]{1,31})";
|
||||
const PCT_ENCODED$ = "(?:\\%[0-9A-Fa-f]{2})";
|
||||
const TRANS$$ = "[0-9A-Za-z\\(\\)\\+\\,\\-\\.\\:\\=\\@\\;\\$\\_\\!\\*\\'\\/\\?\\#]";
|
||||
const NSS$ = "(?:(?:" + PCT_ENCODED$ + "|" + TRANS$$ + ")+)";
|
||||
const URN_SCHEME = new RegExp("^urn\\:(" + NID$ + ")$");
|
||||
const URN_PATH = new RegExp("^(" + NID$ + ")\\:(" + NSS$ + ")$");
|
||||
const URN_PARSE = /^([^\:]+)\:(.*)/;
|
||||
const URN_EXCLUDED = /[\x00-\x20\\\"\&\<\>\[\]\^\`\{\|\}\~\x7F-\xFF]/g;
|
||||
//RFC 2141
|
||||
const handler = {
|
||||
scheme: "urn",
|
||||
parse: function (components, options) {
|
||||
const matches = components.path && components.path.match(URN_PARSE);
|
||||
let urnComponents = components;
|
||||
if (matches) {
|
||||
const scheme = options.scheme || urnComponents.scheme || "urn";
|
||||
const nid = matches[1].toLowerCase();
|
||||
const nss = matches[2];
|
||||
const urnScheme = `${scheme}:${options.nid || nid}`;
|
||||
const schemeHandler = SCHEMES[urnScheme];
|
||||
urnComponents.nid = nid;
|
||||
urnComponents.nss = nss;
|
||||
urnComponents.path = undefined;
|
||||
if (schemeHandler) {
|
||||
urnComponents = schemeHandler.parse(urnComponents, options);
|
||||
}
|
||||
}
|
||||
else {
|
||||
urnComponents.error = urnComponents.error || "URN can not be parsed.";
|
||||
}
|
||||
return urnComponents;
|
||||
},
|
||||
serialize: function (urnComponents, options) {
|
||||
const scheme = options.scheme || urnComponents.scheme || "urn";
|
||||
const nid = urnComponents.nid;
|
||||
const urnScheme = `${scheme}:${options.nid || nid}`;
|
||||
const schemeHandler = SCHEMES[urnScheme];
|
||||
if (schemeHandler) {
|
||||
urnComponents = schemeHandler.serialize(urnComponents, options);
|
||||
}
|
||||
const uriComponents = urnComponents;
|
||||
const nss = urnComponents.nss;
|
||||
uriComponents.path = `${nid || options.nid}:${nss}`;
|
||||
return uriComponents;
|
||||
},
|
||||
};
|
||||
export default handler;
|
||||
//# sourceMappingURL=urn.js.map
|
||||
@@ -0,0 +1,42 @@
|
||||
module.exports = isexe
|
||||
isexe.sync = sync
|
||||
|
||||
var fs = require('fs')
|
||||
|
||||
function checkPathExt (path, options) {
|
||||
var pathext = options.pathExt !== undefined ?
|
||||
options.pathExt : process.env.PATHEXT
|
||||
|
||||
if (!pathext) {
|
||||
return true
|
||||
}
|
||||
|
||||
pathext = pathext.split(';')
|
||||
if (pathext.indexOf('') !== -1) {
|
||||
return true
|
||||
}
|
||||
for (var i = 0; i < pathext.length; i++) {
|
||||
var p = pathext[i].toLowerCase()
|
||||
if (p && path.substr(-p.length).toLowerCase() === p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function checkStat (stat, path, options) {
|
||||
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
||||
return false
|
||||
}
|
||||
return checkPathExt(path, options)
|
||||
}
|
||||
|
||||
function isexe (path, options, cb) {
|
||||
fs.stat(path, function (er, stat) {
|
||||
cb(er, er ? false : checkStat(stat, path, options))
|
||||
})
|
||||
}
|
||||
|
||||
function sync (path, options) {
|
||||
return checkStat(fs.statSync(path), path, options)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
import stringify from './stringify.js';
|
||||
import parse from './parse.js';
|
||||
|
||||
function stringToBytes(str) {
|
||||
str = unescape(encodeURIComponent(str)); // UTF8 escape
|
||||
|
||||
const bytes = [];
|
||||
|
||||
for (let i = 0; i < str.length; ++i) {
|
||||
bytes.push(str.charCodeAt(i));
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
|
||||
export const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
|
||||
export default function (name, version, hashfunc) {
|
||||
function generateUUID(value, namespace, buf, offset) {
|
||||
if (typeof value === 'string') {
|
||||
value = stringToBytes(value);
|
||||
}
|
||||
|
||||
if (typeof namespace === 'string') {
|
||||
namespace = parse(namespace);
|
||||
}
|
||||
|
||||
if (namespace.length !== 16) {
|
||||
throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)');
|
||||
} // Compute hash of namespace and value, Per 4.3
|
||||
// Future: Use spread syntax when supported on all platforms, e.g. `bytes =
|
||||
// hashfunc([...namespace, ... value])`
|
||||
|
||||
|
||||
let bytes = new Uint8Array(16 + value.length);
|
||||
bytes.set(namespace);
|
||||
bytes.set(value, namespace.length);
|
||||
bytes = hashfunc(bytes);
|
||||
bytes[6] = bytes[6] & 0x0f | version;
|
||||
bytes[8] = bytes[8] & 0x3f | 0x80;
|
||||
|
||||
if (buf) {
|
||||
offset = offset || 0;
|
||||
|
||||
for (let i = 0; i < 16; ++i) {
|
||||
buf[offset + i] = bytes[i];
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
return stringify(bytes);
|
||||
} // Function#name is not settable on some platforms (#270)
|
||||
|
||||
|
||||
try {
|
||||
generateUUID.name = name; // eslint-disable-next-line no-empty
|
||||
} catch (err) {} // For CommonJS default export support
|
||||
|
||||
|
||||
generateUUID.DNS = DNS;
|
||||
generateUUID.URL = URL;
|
||||
return generateUUID;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { TSESTree } from '@typescript-eslint/types';
|
||||
import type { PatternVisitorCallback, PatternVisitorOptions } from './PatternVisitor';
|
||||
import type { VisitorOptions } from './VisitorBase';
|
||||
import { VisitorBase } from './VisitorBase';
|
||||
interface VisitPatternOptions extends PatternVisitorOptions {
|
||||
processRightHandNodes?: boolean;
|
||||
}
|
||||
export declare class Visitor extends VisitorBase {
|
||||
#private;
|
||||
constructor(optionsOrVisitor: Visitor | VisitorOptions);
|
||||
protected visitPattern(node: TSESTree.Node, callback: PatternVisitorCallback, options?: VisitPatternOptions): void;
|
||||
}
|
||||
export { VisitorBase, type VisitorOptions } from './VisitorBase';
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Escape all magic characters in a glob pattern.
|
||||
*
|
||||
* If the {@link MinimatchOptions.windowsPathsNoEscape}
|
||||
* option is used, then characters are escaped by wrapping in `[]`, because
|
||||
* a magic character wrapped in a character class can only be satisfied by
|
||||
* that exact character. In this mode, `\` is _not_ escaped, because it is
|
||||
* not interpreted as a magic character, but instead as a path separator.
|
||||
*
|
||||
* If the {@link MinimatchOptions.magicalBraces} option is used,
|
||||
* then braces (`{` and `}`) will be escaped.
|
||||
*/
|
||||
export const escape = (s, { windowsPathsNoEscape = false, magicalBraces = false, } = {}) => {
|
||||
// don't need to escape +@! because we escape the parens
|
||||
// that make those magic, and escaping ! as [!] isn't valid,
|
||||
// because [!]] is a valid glob class meaning not ']'.
|
||||
if (magicalBraces) {
|
||||
return windowsPathsNoEscape ?
|
||||
s.replace(/[?*()[\]{}]/g, '[$&]')
|
||||
: s.replace(/[?*()[\]\\{}]/g, '\\$&');
|
||||
}
|
||||
return windowsPathsNoEscape ?
|
||||
s.replace(/[?*()[\]]/g, '[$&]')
|
||||
: s.replace(/[?*()[\]\\]/g, '\\$&');
|
||||
};
|
||||
//# sourceMappingURL=escape.js.map
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"reg": {
|
||||
"name": "reg",
|
||||
"browser": "Safari 10.0.1 (Mac OS X 10.12.1)",
|
||||
"suite": "escape-long",
|
||||
"hz": 338041.79919469816,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.028614838392745215,
|
||||
"rhz": 0.37806329872403155,
|
||||
"sampleSize": 167
|
||||
},
|
||||
"fn if": {
|
||||
"name": "fn if",
|
||||
"browser": "Safari 10.0.1 (Mac OS X 10.12.1)",
|
||||
"suite": "escape-long",
|
||||
"hz": 93369.49659361344,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.02106853001441757,
|
||||
"rhz": 0.10442371318125844,
|
||||
"sampleSize": 167
|
||||
},
|
||||
"fn if reverse": {
|
||||
"name": "fn if reverse",
|
||||
"browser": "Safari 10.0.1 (Mac OS X 10.12.1)",
|
||||
"suite": "escape-long",
|
||||
"hz": 83557.77738018853,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.016320452691922446,
|
||||
"rhz": 0.09345036331500452,
|
||||
"sampleSize": 169
|
||||
},
|
||||
"escape31": {
|
||||
"name": "escape31",
|
||||
"browser": "Safari 10.0.1 (Mac OS X 10.12.1)",
|
||||
"suite": "escape-long",
|
||||
"hz": 100947.54042740246,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.013158480020082207,
|
||||
"rhz": 0.11289893800997104,
|
||||
"sampleSize": 173
|
||||
},
|
||||
"native": {
|
||||
"name": "native",
|
||||
"browser": "Safari 10.0.1 (Mac OS X 10.12.1)",
|
||||
"suite": "escape-long",
|
||||
"hz": 894140.7439854478,
|
||||
"success": true,
|
||||
"fastest": true,
|
||||
"rme": 0.028000583912129402,
|
||||
"rhz": 1,
|
||||
"sampleSize": 168
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createSourceFile = createSourceFile;
|
||||
exports.createNoProgram = createNoProgram;
|
||||
const debug_1 = __importDefault(require("debug"));
|
||||
const ts = __importStar(require("typescript"));
|
||||
const source_files_1 = require("../source-files");
|
||||
const getScriptKind_1 = require("./getScriptKind");
|
||||
const log = (0, debug_1.default)('typescript-eslint:typescript-estree:create-program:createSourceFile');
|
||||
function createSourceFile(parseSettings) {
|
||||
log('Getting AST without type information in %s mode for: %s', parseSettings.jsx ? 'TSX' : 'TS', parseSettings.filePath);
|
||||
return (0, source_files_1.isSourceFile)(parseSettings.code)
|
||||
? parseSettings.code
|
||||
: ts.createSourceFile(parseSettings.filePath, parseSettings.codeFullText, {
|
||||
jsDocParsingMode: parseSettings.jsDocParsingMode,
|
||||
languageVersion: ts.ScriptTarget.Latest,
|
||||
setExternalModuleIndicator: parseSettings.setExternalModuleIndicator,
|
||||
},
|
||||
/* setParentNodes */ true, (0, getScriptKind_1.getScriptKind)(parseSettings.filePath, parseSettings.jsx));
|
||||
}
|
||||
function createNoProgram(parseSettings) {
|
||||
return {
|
||||
ast: createSourceFile(parseSettings),
|
||||
program: null,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string format methods", () => {
|
||||
const a = z.email().min(10);
|
||||
const b = z.email().max(10);
|
||||
const c = z.email().length(10);
|
||||
const d = z.email().uppercase();
|
||||
const e = z.email().lowercase();
|
||||
|
||||
// Positive and negative cases for `a`
|
||||
expect(a.safeParse("longemail@example.com").success).toBe(true); // Positive
|
||||
expect(a.safeParse("ort@e.co").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `b`
|
||||
expect(b.safeParse("sho@e.co").success).toBe(true); // Positive
|
||||
expect(b.safeParse("longemail@example.com").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `c`
|
||||
expect(c.safeParse("56780@e.co").success).toBe(true); // Positive
|
||||
expect(c.safeParse("shoasdfasdfrt@e.co").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `d`
|
||||
expect(d.safeParse("EMAIL@EXAMPLE.COM").success).toBe(true); // Positive
|
||||
expect(d.safeParse("email@example.com").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `e`
|
||||
expect(e.safeParse("email@example.com").success).toBe(true); // Positive
|
||||
expect(e.safeParse("EMAIL@EXAMPLE.COM").success).toBe(false); // Negative
|
||||
});
|
||||
|
||||
test("z.stringFormat", () => {
|
||||
const ccRegex = /^(?:\d{14,19}|\d{4}(?: \d{3,6}){2,4}|\d{4}(?:-\d{3,6}){2,4})$/u;
|
||||
|
||||
const a = z
|
||||
.stringFormat("creditCard", (val) => ccRegex.test(val), {
|
||||
error: `Invalid credit card number`,
|
||||
})
|
||||
.refine((_) => false, "Also bad");
|
||||
|
||||
expect(a.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "creditCard",
|
||||
"path": [],
|
||||
"message": "Invalid credit card number"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(a.safeParse("1234-5678-9012-3456")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(a.def.pattern).toMatchInlineSnapshot(`undefined`);
|
||||
|
||||
const b = z
|
||||
.stringFormat("creditCard", ccRegex, {
|
||||
abort: true,
|
||||
error: `Invalid credit card number`,
|
||||
})
|
||||
.refine((_) => false, "Also bad");
|
||||
|
||||
expect(b.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "creditCard",
|
||||
"path": [],
|
||||
"message": "Invalid credit card number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(b.safeParse("1234-5678-9012-3456")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(b.def.pattern).toMatchInlineSnapshot(
|
||||
`/\\^\\(\\?:\\\\d\\{14,19\\}\\|\\\\d\\{4\\}\\(\\?: \\\\d\\{3,6\\}\\)\\{2,4\\}\\|\\\\d\\{4\\}\\(\\?:-\\\\d\\{3,6\\}\\)\\{2,4\\}\\)\\$/u`
|
||||
);
|
||||
});
|
||||
|
||||
test("z.hex", () => {
|
||||
const hexSchema = z.hex();
|
||||
|
||||
// Valid hex strings
|
||||
expect(hexSchema.safeParse("").success).toBe(true); // Empty string is valid hex
|
||||
expect(hexSchema.safeParse("123abc").success).toBe(true);
|
||||
expect(hexSchema.safeParse("DEADBEEF").success).toBe(true);
|
||||
expect(hexSchema.safeParse("0123456789abcdefABCDEF").success).toBe(true);
|
||||
|
||||
// Invalid hex strings
|
||||
expect(hexSchema.safeParse("xyz").success).toBe(false);
|
||||
expect(hexSchema.safeParse("123g").success).toBe(false);
|
||||
expect(hexSchema.safeParse("hello world").success).toBe(false);
|
||||
expect(hexSchema.safeParse("123-abc").success).toBe(false);
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"browser": {
|
||||
"node:crypto": false
|
||||
},
|
||||
"node": {
|
||||
"./crypto": "./esm/cryptoNode.js"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import classApplyDescriptorGet from "./classApplyDescriptorGet.js";
|
||||
import classPrivateFieldGet2 from "./classPrivateFieldGet2.js";
|
||||
function _classPrivateFieldGet(e, t) {
|
||||
var r = classPrivateFieldGet2(t, e);
|
||||
return classApplyDescriptorGet(e, r);
|
||||
}
|
||||
export { _classPrivateFieldGet as default };
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"escape.js","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,CAAS,EACT,EACE,oBAAoB,GAAG,KAAK,EAC5B,aAAa,GAAG,KAAK,MAC+C,EAAE,EACxE,EAAE;IACF,wDAAwD;IACxD,4DAA4D;IAC5D,sDAAsD;IACtD,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,oBAAoB,CAAC,CAAC;YACzB,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC;YACnC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAA;IACzC,CAAC;IACD,OAAO,oBAAoB,CAAC,CAAC;QACzB,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC;QACjC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;AACvC,CAAC,CAAA","sourcesContent":["import type { MinimatchOptions } from './index.js'\n\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n *\n * If the {@link MinimatchOptions.magicalBraces} option is used,\n * then braces (`{` and `}`) will be escaped.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]{}]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\{}]/g, '\\\\$&')\n }\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n"]}
|
||||
@@ -0,0 +1,115 @@
|
||||
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: "karakter", verb: "memiliki" },
|
||||
file: { unit: "byte", verb: "memiliki" },
|
||||
array: { unit: "item", verb: "memiliki" },
|
||||
set: { unit: "item", verb: "memiliki" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const FormatDictionary: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "input",
|
||||
email: "alamat email",
|
||||
url: "URL",
|
||||
emoji: "emoji",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "tanggal dan waktu format ISO",
|
||||
date: "tanggal format ISO",
|
||||
time: "jam format ISO",
|
||||
duration: "durasi format ISO",
|
||||
ipv4: "alamat IPv4",
|
||||
ipv6: "alamat IPv6",
|
||||
cidrv4: "rentang alamat IPv4",
|
||||
cidrv6: "rentang alamat IPv6",
|
||||
base64: "string dengan enkode base64",
|
||||
base64url: "string dengan enkode base64url",
|
||||
json_string: "string JSON",
|
||||
e164: "angka E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "input",
|
||||
};
|
||||
|
||||
const TypeDictionary: {
|
||||
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
|
||||
} = {
|
||||
nan: "NaN",
|
||||
};
|
||||
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `Input tidak valid: diharapkan instanceof ${issue.expected}, diterima ${received}`;
|
||||
}
|
||||
return `Input tidak valid: diharapkan ${expected}, diterima ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Input tidak valid: diharapkan ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Pilihan tidak valid: diharapkan salah satu dari ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Terlalu besar: diharapkan ${issue.origin ?? "value"} memiliki ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elemen"}`;
|
||||
return `Terlalu besar: diharapkan ${issue.origin ?? "value"} menjadi ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Terlalu kecil: diharapkan ${issue.origin} memiliki ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `Terlalu kecil: diharapkan ${issue.origin} menjadi ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `String tidak valid: harus dimulai dengan "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with") return `String tidak valid: harus berakhir dengan "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `String tidak valid: harus menyertakan "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `String tidak valid: harus sesuai pola ${_issue.pattern}`;
|
||||
return `${FormatDictionary[_issue.format] ?? issue.format} tidak valid`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Angka tidak valid: harus kelipatan dari ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `Kunci tidak dikenali ${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Kunci tidak valid di ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Input tidak valid";
|
||||
case "invalid_element":
|
||||
return `Nilai tidak valid di ${issue.origin}`;
|
||||
default:
|
||||
return `Input tidak valid`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"signatureKind.enum.d.ts","sourceRoot":"","sources":["../../src/enums/signatureKind.enum.ts"],"names":[],"mappings":"AAEA,oBAAY,aAAa;IACrB,IAAI,IAAI;IACR,SAAS,IAAI;CAChB"}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("Romanian locale uses 'șir' instead of 'string'", () => {
|
||||
z.setErrorMap(z.locales.ro().localeError);
|
||||
|
||||
// Test 1: Invalid type (Expected string, received number)
|
||||
const stringSchema = z.string();
|
||||
const numberResult = stringSchema.safeParse(123);
|
||||
expect(numberResult.success).toBe(false);
|
||||
if (!numberResult.success) {
|
||||
// Expected: "Intrare invalidă: așteptat șir, primit număr"
|
||||
expect(numberResult.error.issues[0].message).toBe("Intrare invalidă: așteptat șir, primit număr");
|
||||
}
|
||||
|
||||
// Test 2: Invalid base64
|
||||
const base64Schema = z.string().base64();
|
||||
const base64Result = base64Schema.safeParse("not base64!");
|
||||
expect(base64Result.success).toBe(false);
|
||||
if (!base64Result.success) {
|
||||
// Expected: "Format invalid: șir codat base64"
|
||||
expect(base64Result.error.issues[0].message).toBe("Format invalid: șir codat base64");
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,74 @@
|
||||
import { _ as _overload_yield } from "./_overload_yield.js";
|
||||
|
||||
function _async_generator(gen) {
|
||||
var front, back;
|
||||
|
||||
function send(key, arg) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null };
|
||||
if (back) back = back.next = request;
|
||||
else {
|
||||
front = back = request;
|
||||
resume(key, arg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resume(key, arg) {
|
||||
try {
|
||||
var result = gen[key](arg);
|
||||
var value = result.value;
|
||||
var overloaded = value instanceof _overload_yield;
|
||||
Promise.resolve(overloaded ? value.v : value).then(function(arg) {
|
||||
if (overloaded) {
|
||||
var nextKey = key === "return" ? "return" : "next";
|
||||
if (!value.k || arg.done) return resume(nextKey, arg);
|
||||
else arg = gen[nextKey](arg).value;
|
||||
}
|
||||
settle(result.done ? "return" : "normal", arg);
|
||||
}, function(err) {
|
||||
resume("throw", err);
|
||||
});
|
||||
} catch (err) {
|
||||
settle("throw", err);
|
||||
}
|
||||
}
|
||||
|
||||
function settle(type, value) {
|
||||
switch (type) {
|
||||
case "return":
|
||||
front.resolve({ value: value, done: true });
|
||||
break;
|
||||
case "throw":
|
||||
front.reject(value);
|
||||
break;
|
||||
default:
|
||||
front.resolve({ value: value, done: false });
|
||||
break;
|
||||
}
|
||||
front = front.next;
|
||||
if (front) resume(front.key, front.arg);
|
||||
else back = null;
|
||||
}
|
||||
|
||||
this._invoke = send;
|
||||
|
||||
if (typeof gen.return !== "function") this.return = undefined;
|
||||
}
|
||||
|
||||
_async_generator.prototype[(typeof Symbol === "function" && Symbol.asyncIterator) || "@@asyncIterator"] = function() {
|
||||
return this;
|
||||
};
|
||||
|
||||
_async_generator.prototype.next = function(arg) {
|
||||
return this._invoke("next", arg);
|
||||
};
|
||||
|
||||
_async_generator.prototype.throw = function(arg) {
|
||||
return this._invoke("throw", arg);
|
||||
};
|
||||
|
||||
_async_generator.prototype.return = function(arg) {
|
||||
return this._invoke("return", arg);
|
||||
};
|
||||
export { _async_generator as _ };
|
||||
@@ -0,0 +1,364 @@
|
||||
'use strict'
|
||||
/* eslint no-prototype-builtins: 0 */
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const { hostname } = require('node:os')
|
||||
const { join } = require('node:path')
|
||||
const { readFile } = require('node:fs').promises
|
||||
const tspl = require('@matteo.collina/tspl')
|
||||
|
||||
const { sink, match, once, watchFileCreated, file } = require('./helper')
|
||||
const pino = require('../')
|
||||
|
||||
test('level formatter', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
formatters: {
|
||||
level (label, number) {
|
||||
return {
|
||||
log: {
|
||||
level: label
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.info('hello world')
|
||||
match(await o, {
|
||||
log: {
|
||||
level: 'info'
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('bindings formatter', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
formatters: {
|
||||
bindings (bindings) {
|
||||
return {
|
||||
process: {
|
||||
pid: bindings.pid
|
||||
},
|
||||
host: {
|
||||
name: bindings.hostname
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.info('hello world')
|
||||
match(await o, {
|
||||
process: {
|
||||
pid: process.pid
|
||||
},
|
||||
host: {
|
||||
name: hostname()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('no bindings formatter', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
formatters: {
|
||||
bindings (bindings) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.info('hello world')
|
||||
const log = await o
|
||||
assert.equal(log.hasOwnProperty('pid'), false)
|
||||
assert.equal(log.hasOwnProperty('hostname'), false)
|
||||
match(log, { msg: 'hello world' })
|
||||
})
|
||||
|
||||
test('log formatter', async (t) => {
|
||||
const plan = tspl(t, { plan: 1 })
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
formatters: {
|
||||
log (obj) {
|
||||
plan.equal(obj.hasOwnProperty('msg'), false)
|
||||
return { hello: 'world', ...obj }
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
|
||||
match(await o, {
|
||||
hello: 'world',
|
||||
foo: 'bar',
|
||||
nested: { object: true }
|
||||
})
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test('Formatters combined', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
formatters: {
|
||||
level (label, number) {
|
||||
return {
|
||||
log: {
|
||||
level: label
|
||||
}
|
||||
}
|
||||
},
|
||||
bindings (bindings) {
|
||||
return {
|
||||
process: {
|
||||
pid: bindings.pid
|
||||
},
|
||||
host: {
|
||||
name: bindings.hostname
|
||||
}
|
||||
}
|
||||
},
|
||||
log (obj) {
|
||||
return { hello: 'world', ...obj }
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
|
||||
match(await o, {
|
||||
log: {
|
||||
level: 'info'
|
||||
},
|
||||
process: {
|
||||
pid: process.pid
|
||||
},
|
||||
host: {
|
||||
name: hostname()
|
||||
},
|
||||
hello: 'world',
|
||||
foo: 'bar',
|
||||
nested: { object: true }
|
||||
})
|
||||
})
|
||||
|
||||
test('Formatters in child logger', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
formatters: {
|
||||
level (label, number) {
|
||||
return {
|
||||
log: {
|
||||
level: label
|
||||
}
|
||||
}
|
||||
},
|
||||
bindings (bindings) {
|
||||
return {
|
||||
process: {
|
||||
pid: bindings.pid
|
||||
},
|
||||
host: {
|
||||
name: bindings.hostname
|
||||
}
|
||||
}
|
||||
},
|
||||
log (obj) {
|
||||
return { hello: 'world', ...obj }
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const child = logger.child({
|
||||
foo: 'bar',
|
||||
nested: { object: true }
|
||||
}, {
|
||||
formatters: {
|
||||
bindings (bindings) {
|
||||
return { ...bindings, faz: 'baz' }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const o = once(stream, 'data')
|
||||
child.info('hello world')
|
||||
match(await o, {
|
||||
log: {
|
||||
level: 'info'
|
||||
},
|
||||
process: {
|
||||
pid: process.pid
|
||||
},
|
||||
host: {
|
||||
name: hostname()
|
||||
},
|
||||
hello: 'world',
|
||||
foo: 'bar',
|
||||
nested: { object: true },
|
||||
faz: 'baz'
|
||||
})
|
||||
})
|
||||
|
||||
test('Formatters without bindings in child logger', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
formatters: {
|
||||
level (label, number) {
|
||||
return {
|
||||
log: {
|
||||
level: label
|
||||
}
|
||||
}
|
||||
},
|
||||
bindings (bindings) {
|
||||
return {
|
||||
process: {
|
||||
pid: bindings.pid
|
||||
},
|
||||
host: {
|
||||
name: bindings.hostname
|
||||
}
|
||||
}
|
||||
},
|
||||
log (obj) {
|
||||
return { hello: 'world', ...obj }
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
const child = logger.child({
|
||||
foo: 'bar',
|
||||
nested: { object: true }
|
||||
}, {
|
||||
formatters: {
|
||||
log (obj) {
|
||||
return { other: 'stuff', ...obj }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const o = once(stream, 'data')
|
||||
child.info('hello world')
|
||||
match(await o, {
|
||||
log: {
|
||||
level: 'info'
|
||||
},
|
||||
process: {
|
||||
pid: process.pid
|
||||
},
|
||||
host: {
|
||||
name: hostname()
|
||||
},
|
||||
foo: 'bar',
|
||||
other: 'stuff',
|
||||
nested: { object: true }
|
||||
})
|
||||
})
|
||||
|
||||
test('elastic common schema format', async () => {
|
||||
const stream = sink()
|
||||
const ecs = {
|
||||
formatters: {
|
||||
level (label, number) {
|
||||
return {
|
||||
log: {
|
||||
level: label,
|
||||
logger: 'pino'
|
||||
}
|
||||
}
|
||||
},
|
||||
bindings (bindings) {
|
||||
return {
|
||||
process: {
|
||||
pid: bindings.pid
|
||||
},
|
||||
host: {
|
||||
name: bindings.hostname
|
||||
}
|
||||
}
|
||||
},
|
||||
log (obj) {
|
||||
return { ecs: { version: '1.4.0' }, ...obj }
|
||||
}
|
||||
},
|
||||
messageKey: 'message',
|
||||
timestamp: () => `,"@timestamp":"${new Date(Date.now()).toISOString()}"`
|
||||
}
|
||||
|
||||
const logger = pino({ ...ecs }, stream)
|
||||
|
||||
const o = once(stream, 'data')
|
||||
logger.info({ foo: 'bar' }, 'hello world')
|
||||
const log = await o
|
||||
assert.equal(typeof log['@timestamp'], 'string')
|
||||
match(log, {
|
||||
log: { level: 'info', logger: 'pino' },
|
||||
process: { pid: process.pid },
|
||||
host: { name: hostname() },
|
||||
ecs: { version: '1.4.0' },
|
||||
foo: 'bar',
|
||||
message: 'hello world'
|
||||
})
|
||||
})
|
||||
|
||||
test('formatter with transport', async (t) => {
|
||||
const plan = tspl(t, { plan: 1 })
|
||||
const destination = file()
|
||||
const logger = pino({
|
||||
formatters: {
|
||||
log (obj) {
|
||||
plan.equal(obj.hasOwnProperty('msg'), false)
|
||||
return { hello: 'world', ...obj }
|
||||
}
|
||||
},
|
||||
transport: {
|
||||
targets: [
|
||||
{
|
||||
target: join(__dirname, 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination }
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
match(result, {
|
||||
hello: 'world',
|
||||
foo: 'bar',
|
||||
nested: { object: true }
|
||||
})
|
||||
})
|
||||
|
||||
test('throws when custom level formatter is used with transport.targets', async () => {
|
||||
assert.throws(
|
||||
() => {
|
||||
pino({
|
||||
formatters: {
|
||||
level (label) {
|
||||
return label
|
||||
}
|
||||
},
|
||||
transport: {
|
||||
targets: [
|
||||
{
|
||||
target: 'pino/file',
|
||||
options: { destination: 'foo.log' }
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
Error('option.transport.targets do not allow custom level formatters')
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
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 Variable from "./variable.js";
|
||||
|
||||
/** @import * as types from "eslint-scope" */
|
||||
|
||||
// Cannot implement `types.Definition` directly because it contains a union.
|
||||
/**
|
||||
* @constructor Definition
|
||||
* @implements {Omit<types.Definition, never>}
|
||||
*/
|
||||
class Definition {
|
||||
constructor(type, name, node, parent, index, kind) {
|
||||
/**
|
||||
* @member {string} Definition#type - type of the occurrence (e.g. "Parameter", "Variable", ...).
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* @member {espree.Identifier} Definition#name - the identifier AST node of the occurrence.
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* @member {espree.Node} Definition#node - the enclosing node of the identifier.
|
||||
*/
|
||||
this.node = node;
|
||||
|
||||
/**
|
||||
* @member {espree.Node?} Definition#parent - the enclosing statement node of the identifier.
|
||||
*/
|
||||
this.parent = parent;
|
||||
|
||||
/**
|
||||
* @member {number?} Definition#index - the index in the declaration statement.
|
||||
*/
|
||||
this.index = index;
|
||||
|
||||
/**
|
||||
* @member {string?} Definition#kind - the kind of the declaration statement.
|
||||
*/
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor ParameterDefinition
|
||||
*/
|
||||
class ParameterDefinition extends Definition {
|
||||
constructor(name, node, index, rest) {
|
||||
super(Variable.Parameter, name, node, null, index, null);
|
||||
|
||||
/**
|
||||
* Whether the parameter definition is a part of a rest parameter.
|
||||
* @member {boolean} ParameterDefinition#rest
|
||||
*/
|
||||
this.rest = rest;
|
||||
}
|
||||
}
|
||||
|
||||
export { ParameterDefinition, Definition };
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-present The Fastify team <https://github.com/fastify/fastify#team>
|
||||
|
||||
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,142 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = default_1;
|
||||
const util = __importStar(require("../core/util.cjs"));
|
||||
const error = () => {
|
||||
const Sizable = {
|
||||
string: { unit: "tegn", verb: "havde" },
|
||||
file: { unit: "bytes", verb: "havde" },
|
||||
array: { unit: "elementer", verb: "indeholdt" },
|
||||
set: { unit: "elementer", verb: "indeholdt" },
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "input",
|
||||
email: "e-mailadresse",
|
||||
url: "URL",
|
||||
emoji: "emoji",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "ISO dato- og klokkeslæt",
|
||||
date: "ISO-dato",
|
||||
time: "ISO-klokkeslæt",
|
||||
duration: "ISO-varighed",
|
||||
ipv4: "IPv4-område",
|
||||
ipv6: "IPv6-område",
|
||||
cidrv4: "IPv4-spektrum",
|
||||
cidrv6: "IPv6-spektrum",
|
||||
base64: "base64-kodet streng",
|
||||
base64url: "base64url-kodet streng",
|
||||
json_string: "JSON-streng",
|
||||
e164: "E.164-nummer",
|
||||
jwt: "JWT",
|
||||
template_literal: "input",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
string: "streng",
|
||||
number: "tal",
|
||||
boolean: "boolean",
|
||||
array: "liste",
|
||||
object: "objekt",
|
||||
set: "sæt",
|
||||
file: "fil",
|
||||
};
|
||||
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 `Ugyldigt input: forventede instanceof ${issue.expected}, fik ${received}`;
|
||||
}
|
||||
return `Ugyldigt input: forventede ${expected}, fik ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Ugyldig værdi: forventede ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Ugyldigt valg: forventede en af følgende ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
const origin = TypeDictionary[issue.origin] ?? issue.origin;
|
||||
if (sizing)
|
||||
return `For stor: forventede ${origin ?? "value"} ${sizing.verb} ${adj} ${issue.maximum.toString()} ${sizing.unit ?? "elementer"}`;
|
||||
return `For stor: forventede ${origin ?? "value"} havde ${adj} ${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
const origin = TypeDictionary[issue.origin] ?? issue.origin;
|
||||
if (sizing) {
|
||||
return `For lille: forventede ${origin} ${sizing.verb} ${adj} ${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `For lille: forventede ${origin} havde ${adj} ${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with")
|
||||
return `Ugyldig streng: skal starte med "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with")
|
||||
return `Ugyldig streng: skal ende med "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes")
|
||||
return `Ugyldig streng: skal indeholde "${_issue.includes}"`;
|
||||
if (_issue.format === "regex")
|
||||
return `Ugyldig streng: skal matche mønsteret ${_issue.pattern}`;
|
||||
return `Ugyldig ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Ugyldigt tal: skal være deleligt med ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `${issue.keys.length > 1 ? "Ukendte nøgler" : "Ukendt nøgle"}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Ugyldig nøgle i ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Ugyldigt input: matcher ingen af de tilladte typer";
|
||||
case "invalid_element":
|
||||
return `Ugyldig værdi i ${issue.origin}`;
|
||||
default:
|
||||
return `Ugyldigt input`;
|
||||
}
|
||||
};
|
||||
};
|
||||
function default_1() {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
module.exports = exports.default;
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CORE_COMPILER_OPTIONS = void 0;
|
||||
/**
|
||||
* Compiler options required to avoid critical functionality issues
|
||||
*/
|
||||
exports.CORE_COMPILER_OPTIONS = {
|
||||
// Required to avoid parse from causing emit to occur
|
||||
noEmit: true,
|
||||
// Flags required to make no-unused-vars work
|
||||
noUnusedLocals: true,
|
||||
noUnusedParameters: true,
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
# `@typescript-eslint/eslint-plugin`
|
||||
|
||||
An ESLint plugin which provides lint rules for TypeScript codebases.
|
||||
|
||||
[](https://www.npmjs.com/package/@typescript-eslint/eslint-plugin)
|
||||
[](https://www.npmjs.com/package/@typescript-eslint/eslint-plugin)
|
||||
|
||||
👉 See **https://typescript-eslint.io/getting-started** for our Getting Started docs.
|
||||
|
||||
> See https://typescript-eslint.io for general documentation on typescript-eslint, the tooling that allows you to run ESLint and Prettier on TypeScript code.
|
||||
|
||||
<!-- Local path for docs: docs/packages/ESLint_Plugin.mdx -->
|
||||
@@ -0,0 +1,129 @@
|
||||
import { Codec, Decoder, Encoder, FixedSizeCodec, FixedSizeDecoder, FixedSizeEncoder } from './codec';
|
||||
type AnyEncoder = Encoder<any>;
|
||||
type AnyDecoder = Decoder<any>;
|
||||
type AnyCodec = Codec<any>;
|
||||
/**
|
||||
* Updates the size of a given encoder.
|
||||
*
|
||||
* This function modifies the size of an encoder using a provided transformation function.
|
||||
* For fixed-size encoders, it updates the `fixedSize` property, and for variable-size
|
||||
* encoders, it adjusts the size calculation based on the encoded value.
|
||||
*
|
||||
* If the new size is negative, an error will be thrown.
|
||||
*
|
||||
* For more details, see {@link resizeCodec}.
|
||||
*
|
||||
* @typeParam TFrom - The type of the value to encode.
|
||||
* @typeParam TSize - The original fixed size of the encoded value.
|
||||
* @typeParam TNewSize - The new fixed size after resizing.
|
||||
*
|
||||
* @param encoder - The encoder whose size will be updated.
|
||||
* @param resize - A function that takes the current size and returns the new size.
|
||||
* @returns A new encoder with the updated size.
|
||||
*
|
||||
* @example
|
||||
* Increasing the size of a `u16` encoder by 2 bytes.
|
||||
* ```ts
|
||||
* const encoder = resizeEncoder(getU16Encoder(), size => size + 2);
|
||||
* encoder.encode(0xffff); // 0xffff0000 (two extra bytes added)
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* Shrinking a `u32` encoder to only use 2 bytes.
|
||||
* ```ts
|
||||
* const encoder = resizeEncoder(getU32Encoder(), () => 2);
|
||||
* encoder.fixedSize; // 2
|
||||
* ```
|
||||
*
|
||||
* @see {@link resizeCodec}
|
||||
* @see {@link resizeDecoder}
|
||||
*/
|
||||
export declare function resizeEncoder<TFrom, TSize extends number, TNewSize extends number>(encoder: FixedSizeEncoder<TFrom, TSize>, resize: (size: TSize) => TNewSize): FixedSizeEncoder<TFrom, TNewSize>;
|
||||
export declare function resizeEncoder<TEncoder extends AnyEncoder>(encoder: TEncoder, resize: (size: number) => number): TEncoder;
|
||||
/**
|
||||
* Updates the size of a given decoder.
|
||||
*
|
||||
* This function modifies the size of a decoder using a provided transformation function.
|
||||
* For fixed-size decoders, it updates the `fixedSize` property to reflect the new size.
|
||||
* Variable-size decoders remain unchanged, as their size is determined dynamically.
|
||||
*
|
||||
* If the new size is negative, an error will be thrown.
|
||||
*
|
||||
* For more details, see {@link resizeCodec}.
|
||||
*
|
||||
* @typeParam TTo - The type of the decoded value.
|
||||
* @typeParam TSize - The original fixed size of the decoded value.
|
||||
* @typeParam TNewSize - The new fixed size after resizing.
|
||||
*
|
||||
* @param decoder - The decoder whose size will be updated.
|
||||
* @param resize - A function that takes the current size and returns the new size.
|
||||
* @returns A new decoder with the updated size.
|
||||
*
|
||||
* @example
|
||||
* Expanding a `u16` decoder to read 4 bytes instead of 2.
|
||||
* ```ts
|
||||
* const decoder = resizeDecoder(getU16Decoder(), size => size + 2);
|
||||
* decoder.fixedSize; // 4
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* Shrinking a `u32` decoder to only read 2 bytes.
|
||||
* ```ts
|
||||
* const decoder = resizeDecoder(getU32Decoder(), () => 2);
|
||||
* decoder.fixedSize; // 2
|
||||
* ```
|
||||
*
|
||||
* @see {@link resizeCodec}
|
||||
* @see {@link resizeEncoder}
|
||||
*/
|
||||
export declare function resizeDecoder<TFrom, TSize extends number, TNewSize extends number>(decoder: FixedSizeDecoder<TFrom, TSize>, resize: (size: TSize) => TNewSize): FixedSizeDecoder<TFrom, TNewSize>;
|
||||
export declare function resizeDecoder<TDecoder extends AnyDecoder>(decoder: TDecoder, resize: (size: number) => number): TDecoder;
|
||||
/**
|
||||
* Updates the size of a given codec.
|
||||
*
|
||||
* This function modifies the size of both the codec using a provided
|
||||
* transformation function. It is useful for adjusting the allocated byte size for
|
||||
* encoding and decoding without altering the underlying data structure.
|
||||
*
|
||||
* If the new size is negative, an error will be thrown.
|
||||
*
|
||||
* @typeParam TFrom - The type of the value to encode.
|
||||
* @typeParam TTo - The type of the decoded value.
|
||||
* @typeParam TSize - The original fixed size of the encoded/decoded value (for fixed-size codecs).
|
||||
* @typeParam TNewSize - The new fixed size after resizing (for fixed-size codecs).
|
||||
*
|
||||
* @param codec - The codec whose size will be updated.
|
||||
* @param resize - A function that takes the current size and returns the new size.
|
||||
* @returns A new codec with the updated size.
|
||||
*
|
||||
* @example
|
||||
* Expanding a `u16` codec from 2 to 4 bytes.
|
||||
* ```ts
|
||||
* const codec = resizeCodec(getU16Codec(), size => size + 2);
|
||||
* const bytes = codec.encode(0xffff); // 0xffff0000 (two extra bytes added)
|
||||
* const value = codec.decode(bytes); // 0xffff (reads original two bytes)
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* Shrinking a `u32` codec to only use 2 bytes.
|
||||
* ```ts
|
||||
* const codec = resizeCodec(getU32Codec(), () => 2);
|
||||
* codec.fixedSize; // 2
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* If you only need to resize an encoder, use {@link resizeEncoder}.
|
||||
* If you only need to resize a decoder, use {@link resizeDecoder}.
|
||||
*
|
||||
* ```ts
|
||||
* const bytes = resizeEncoder(getU32Encoder(), (size) => size + 2).encode(0xffff);
|
||||
* const value = resizeDecoder(getU32Decoder(), (size) => size + 2).decode(bytes);
|
||||
* ```
|
||||
*
|
||||
* @see {@link resizeEncoder}
|
||||
* @see {@link resizeDecoder}
|
||||
*/
|
||||
export declare function resizeCodec<TFrom, TTo extends TFrom, TSize extends number, TNewSize extends number>(codec: FixedSizeCodec<TFrom, TTo, TSize>, resize: (size: TSize) => TNewSize): FixedSizeCodec<TFrom, TTo, TNewSize>;
|
||||
export declare function resizeCodec<TCodec extends AnyCodec>(codec: TCodec, resize: (size: number) => number): TCodec;
|
||||
export {};
|
||||
//# sourceMappingURL=resize-codec.d.ts.map
|
||||
@@ -0,0 +1,130 @@
|
||||
[![npm][npm-image]][npm-url]
|
||||
[![npm-downloads][npm-downloads-image]][npm-url]
|
||||
<br />
|
||||
[![code-style-prettier][code-style-prettier-image]][code-style-prettier-url]
|
||||
|
||||
[code-style-prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square
|
||||
[code-style-prettier-url]: https://github.com/prettier/prettier
|
||||
[npm-downloads-image]: https://img.shields.io/npm/dm/@solana/codecs-numbers?style=flat
|
||||
[npm-image]: https://img.shields.io/npm/v/@solana/codecs-numbers?style=flat
|
||||
[npm-url]: https://www.npmjs.com/package/@solana/codecs-numbers
|
||||
|
||||
# @solana/codecs-numbers
|
||||
|
||||
This package contains codecs for numbers of different sizes and endianness. It can be used standalone, but it is also exported as part of Kit [`@solana/kit`](https://github.com/anza-xyz/kit/tree/main/packages/kit).
|
||||
|
||||
This package is also part of the [`@solana/codecs` package](https://github.com/anza-xyz/kit/tree/main/packages/codecs) which acts as an entry point for all codec packages as well as for their documentation.
|
||||
|
||||
## Integer codecs
|
||||
|
||||
This package provides ten codecs of five different byte sizes for integers. Five of them store unsigned integers and the other five store signed integers.
|
||||
|
||||
```ts
|
||||
// Unsigned integers.
|
||||
getU8Codec().encode(42); // 0x2a
|
||||
getU16Codec().encode(42); // 0x2a00
|
||||
getU32Codec().encode(42); // 0x2a000000
|
||||
getU64Codec().encode(42); // 0x2a00000000000000
|
||||
getU128Codec().encode(42); // 0x2a000000000000000000000000000000
|
||||
|
||||
// Signed integers.
|
||||
getI8Codec().encode(-42); // 0xd6
|
||||
getI16Codec().encode(-42); // 0xd6ff
|
||||
getI32Codec().encode(-42); // 0xd6ffffff
|
||||
getI64Codec().encode(-42); // 0xd6ffffffffffffff
|
||||
getI128Codec().encode(-42); // 0xd6ffffffffffffffffffffffffffffff
|
||||
```
|
||||
|
||||
By default, integers are stored using little endianness but you may change this behaviour via the `endian` option. This option is available for every codec that uses more than a single byte.
|
||||
|
||||
```ts
|
||||
// Big-endian unsigned integers.
|
||||
getU16Codec({ endian: Endian.Big }).encode(42); // 0x002a
|
||||
getU32Codec({ endian: Endian.Big }).encode(42); // 0x0000002a
|
||||
getU64Codec({ endian: Endian.Big }).encode(42); // 0x000000000000002a
|
||||
getU128Codec({ endian: Endian.Big }).encode(42); // 0x0000000000000000000000000000002a
|
||||
|
||||
// Big-endian signed integers.
|
||||
getI16Codec({ endian: Endian.Big }).encode(-42); // 0xffd6
|
||||
getI32Codec({ endian: Endian.Big }).encode(-42); // 0xffffffd6
|
||||
getI64Codec({ endian: Endian.Big }).encode(-42); // 0xffffffffffffffd6
|
||||
getI128Codec({ endian: Endian.Big }).encode(-42); // 0xffffffffffffffffffffffffffffffd6
|
||||
```
|
||||
|
||||
All integer codecs are of type `Codec<number>` except for the `u64`, `u128`, `i64` and `i128` codecs which are of type `Codec<number | bigint, bigint>`. This means we can provide either a `number` of a `bigint` value to encode but the decoded value will always be a `bigint`. This is because JavaScript's native `number` type does not support numbers larger than `2^53 - 1` and these large integer codecs have the potential to go over that value.
|
||||
|
||||
```ts
|
||||
const bytesFromNumber = getU64Codec().encode(42);
|
||||
getU64Codec().decode(bytesFromNumber); // BigInt(42)
|
||||
|
||||
// OR
|
||||
const bytesFromBigInt = getU64Codec().encode(BigInt(42));
|
||||
getU64Codec().decode(bytesFromBigInt); // BigInt(42)
|
||||
```
|
||||
|
||||
Finally, for each of these `get*Codec` functions, separate `get*Encoder` and `get*Decoder` functions exist to focus on only one side of the serialization and tree-shake the rest of the functions away.
|
||||
|
||||
```ts
|
||||
const bytes = getU8Encoder().encode(42);
|
||||
const value = getU8Decoder().decode(bytes);
|
||||
```
|
||||
|
||||
## Decimal number codecs
|
||||
|
||||
This package also provides two codecs for floating numbers. One using 32 bits and one using 64 bits.
|
||||
|
||||
```ts
|
||||
getF32Codec().encode(-1.5); // 0x0000c0bf
|
||||
getF64Codec().encode(-1.5); // 0x000000000000f8bf
|
||||
```
|
||||
|
||||
Similarly to the integer codecs, they are stored in little-endian by default but may be stored in big-endian using the `endian` option.
|
||||
|
||||
```ts
|
||||
getF32Codec({ endian: Endian.Big }).encode(-1.5); // 0xbfc00000
|
||||
getF64Codec({ endian: Endian.Big }).encode(-1.5); // 0xbff8000000000000
|
||||
```
|
||||
|
||||
Note that based on the selected codec, some of the precision of the number you are encoding may be lost when decoding it. For instance, when storing `3.1415` using a `f32` codec, you will not get the exact same number back.
|
||||
|
||||
```ts
|
||||
const bytes = getF32Codec().encode(3.1415); // 0x560e4940
|
||||
const value = getF32Codec().decode(bytes); // 3.1414999961853027 !== 3.1415
|
||||
```
|
||||
|
||||
As usual, separate encoder and decoder functions are available for these codecs.
|
||||
|
||||
```ts
|
||||
getF32Encoder().encode(-1.5);
|
||||
getF32Decoder().decode(new Uint8Array([...]));
|
||||
|
||||
getF64Encoder().encode(-1.5);
|
||||
getF64Decoder().decode(new Uint8Array([...]));
|
||||
```
|
||||
|
||||
## Short u16 codec
|
||||
|
||||
This last integer codec is less common `VariableSizeCodec` that stores an unsigned integer using between 1 to 3 bytes depending on the value of that integer.
|
||||
|
||||
```ts
|
||||
const bytes = getShortU16Codec().encode(42); // 0x2a
|
||||
const value = getShortU16Codec().decode(bytes); // 42
|
||||
```
|
||||
|
||||
If the provided integer is equal to or lower than `0x7f`, it will be stored as-is, using a single byte. However, if the integer is above `0x7f`, then the top bit is set and the remaining value is stored in the next bytes. Each byte follows the same pattern until the third byte. The third byte, if needed, uses all 8 bits to store the last byte of the original value.
|
||||
|
||||
In other words, this codec provides an extendable size that adapts based on the integer. In the illustration below, you can see the `0` and `1` byte flags for each scenario as well as the available bits to store the integer marked with `X`.
|
||||
|
||||
```
|
||||
0XXXXXXX <- From 0 to 127.
|
||||
1XXXXXXX 0XXXXXXX <- From 128 to 16,383.
|
||||
1XXXXXXX 1XXXXXXX XXXXXXXX <- From 16,384 to 4,194,303.
|
||||
```
|
||||
|
||||
This codec is mainly used internally when encoding and decoding Solana transactions.
|
||||
|
||||
Separate encoder and decoder functions are also available via `getShortU16Encoder` and `getShortU16Decoder` respectively.
|
||||
|
||||
---
|
||||
|
||||
To read more about the available codecs and how to use them, check out the documentation of the main [`@solana/codecs` package](https://github.com/anza-xyz/kit/tree/main/packages/codecs).
|
||||
Reference in New Issue
Block a user