WIP: bootstrap and partial real Solana watcher implementation

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

View File

@@ -0,0 +1,15 @@
/**
* Internal assertion helpers.
* @module
* @deprecated
*/
import { abytes as ab, aexists as ae, anumber as an, aoutput as ao, } from "./utils.js";
/** @deprecated Use import from `noble/hashes/utils` module */
export const abytes = ab;
/** @deprecated Use import from `noble/hashes/utils` module */
export const aexists = ae;
/** @deprecated Use import from `noble/hashes/utils` module */
export const anumber = an;
/** @deprecated Use import from `noble/hashes/utils` module */
export const aoutput = ao;
//# sourceMappingURL=_assert.js.map

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.slugify = exports.toUpperCase = exports.toLowerCase = exports.trim = exports.normalize = exports.overwrite = exports.mime = exports.property = exports.endsWith = exports.startsWith = exports.includes = exports.uppercase = exports.lowercase = exports.regex = exports.length = exports.minLength = exports.maxLength = exports.size = exports.minSize = exports.maxSize = exports.multipleOf = exports.nonnegative = exports.nonpositive = exports.negative = exports.positive = exports.gte = exports.gt = exports.lte = exports.lt = void 0;
var index_js_1 = require("../core/index.cjs");
Object.defineProperty(exports, "lt", { enumerable: true, get: function () { return index_js_1._lt; } });
Object.defineProperty(exports, "lte", { enumerable: true, get: function () { return index_js_1._lte; } });
Object.defineProperty(exports, "gt", { enumerable: true, get: function () { return index_js_1._gt; } });
Object.defineProperty(exports, "gte", { enumerable: true, get: function () { return index_js_1._gte; } });
Object.defineProperty(exports, "positive", { enumerable: true, get: function () { return index_js_1._positive; } });
Object.defineProperty(exports, "negative", { enumerable: true, get: function () { return index_js_1._negative; } });
Object.defineProperty(exports, "nonpositive", { enumerable: true, get: function () { return index_js_1._nonpositive; } });
Object.defineProperty(exports, "nonnegative", { enumerable: true, get: function () { return index_js_1._nonnegative; } });
Object.defineProperty(exports, "multipleOf", { enumerable: true, get: function () { return index_js_1._multipleOf; } });
Object.defineProperty(exports, "maxSize", { enumerable: true, get: function () { return index_js_1._maxSize; } });
Object.defineProperty(exports, "minSize", { enumerable: true, get: function () { return index_js_1._minSize; } });
Object.defineProperty(exports, "size", { enumerable: true, get: function () { return index_js_1._size; } });
Object.defineProperty(exports, "maxLength", { enumerable: true, get: function () { return index_js_1._maxLength; } });
Object.defineProperty(exports, "minLength", { enumerable: true, get: function () { return index_js_1._minLength; } });
Object.defineProperty(exports, "length", { enumerable: true, get: function () { return index_js_1._length; } });
Object.defineProperty(exports, "regex", { enumerable: true, get: function () { return index_js_1._regex; } });
Object.defineProperty(exports, "lowercase", { enumerable: true, get: function () { return index_js_1._lowercase; } });
Object.defineProperty(exports, "uppercase", { enumerable: true, get: function () { return index_js_1._uppercase; } });
Object.defineProperty(exports, "includes", { enumerable: true, get: function () { return index_js_1._includes; } });
Object.defineProperty(exports, "startsWith", { enumerable: true, get: function () { return index_js_1._startsWith; } });
Object.defineProperty(exports, "endsWith", { enumerable: true, get: function () { return index_js_1._endsWith; } });
Object.defineProperty(exports, "property", { enumerable: true, get: function () { return index_js_1._property; } });
Object.defineProperty(exports, "mime", { enumerable: true, get: function () { return index_js_1._mime; } });
Object.defineProperty(exports, "overwrite", { enumerable: true, get: function () { return index_js_1._overwrite; } });
Object.defineProperty(exports, "normalize", { enumerable: true, get: function () { return index_js_1._normalize; } });
Object.defineProperty(exports, "trim", { enumerable: true, get: function () { return index_js_1._trim; } });
Object.defineProperty(exports, "toLowerCase", { enumerable: true, get: function () { return index_js_1._toLowerCase; } });
Object.defineProperty(exports, "toUpperCase", { enumerable: true, get: function () { return index_js_1._toUpperCase; } });
Object.defineProperty(exports, "slugify", { enumerable: true, get: function () { return index_js_1._slugify; } });

View File

@@ -0,0 +1,287 @@
/**
* @fileoverview Main Espree file that converts Acorn into Esprima output.
*
* This file contains code from the following MIT-licensed projects:
* 1. Acorn
* 2. Babylon
* 3. Babel-ESLint
*
* This file also contains code from Esprima, which is BSD licensed.
*
* Acorn is Copyright 2012-2015 Acorn Contributors (https://github.com/marijnh/acorn/blob/master/AUTHORS)
* Babylon is Copyright 2014-2015 various contributors (https://github.com/babel/babel/blob/master/packages/babylon/AUTHORS)
* Babel-ESLint is Copyright 2014-2015 Sebastian McKenzie <sebmck@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.
*
* Esprima is Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
*
* 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 * as acorn from "acorn";
import jsx from "acorn-jsx";
import espree from "./lib/espree.js";
import { KEYS as VisitorKeys } from "eslint-visitor-keys";
import {
getLatestEcmaVersion,
getSupportedEcmaVersions,
} from "./lib/options.js";
/**
* @import { EspreeParserCtor, EspreeParserJsxCtor } from "./lib/types.js";
*/
// ----------------------------------------------------------------------------
// Types exported from file
// ----------------------------------------------------------------------------
/**
* @typedef {3|5|6|7|8|9|10|11|12|13|14|15|16|17|2015|2016|2017|2018|2019|2020|2021|2022|2023|2024|2025|2026|'latest'} EcmaVersion
*/
/**
* @typedef {{
* type: string;
* value: any;
* start?: number;
* end?: number;
* loc?: acorn.SourceLocation;
* range?: [number, number];
* regex?: {flags: string, pattern: string};
* }} EspreeToken
*/
/**
* @typedef {{
* type: "Block" | "Hashbang" | "Line",
* value: string,
* range?: [number, number],
* start?: number,
* end?: number,
* loc?: {
* start: acorn.Position | undefined,
* end: acorn.Position | undefined
* }
* }} EspreeComment
*/
/**
* @typedef {{
* comments?: EspreeComment[]
* } & EspreeToken[]} EspreeTokens
*/
/**
* `allowReserved` is as in `acorn.Options`
*
* `ecmaVersion` currently as in `acorn.Options` though optional
*
* `sourceType` as in `acorn.Options` but also allows `commonjs`
*
* `ecmaFeatures`, `range`, `loc`, `tokens` are not in `acorn.Options`
*
* `comment` is not in `acorn.Options` and doesn't err without it, but is used
*/
/**
* @typedef {{
* allowReserved?: boolean,
* ecmaVersion?: EcmaVersion,
* sourceType?: "script"|"module"|"commonjs",
* ecmaFeatures?: {
* jsx?: boolean,
* globalReturn?: boolean,
* impliedStrict?: boolean
* },
* range?: boolean,
* loc?: boolean,
* tokens?: boolean,
* comment?: boolean,
* }} Options
*/
// To initialize lazily.
const parsers = {
/** @type {EspreeParserCtor|null} */
_regular: null,
/** @type {EspreeParserJsxCtor|null} */
_jsx: null,
/**
* Returns regular Parser
* @returns {EspreeParserCtor} Regular Acorn parser
*/
get regular() {
if (this._regular === null) {
const espreeParserFactory = /** @type {unknown} */ (espree());
this._regular = /** @type {EspreeParserCtor} */ (
// Without conversion, types are incompatible, as
// acorn's has a protected constructor
/** @type {unknown} */
(
acorn.Parser.extend(
/**
* @type {(
* BaseParser: typeof acorn.Parser
* ) => typeof acorn.Parser}
*/ (espreeParserFactory),
)
)
);
}
return this._regular;
},
/**
* Returns JSX Parser
* @returns {EspreeParserJsxCtor} JSX Acorn parser
*/
get jsx() {
if (this._jsx === null) {
const espreeParserFactory = /** @type {unknown} */ (espree());
const jsxFactory = jsx();
this._jsx = /** @type {EspreeParserJsxCtor} */ (
// Without conversion, types are incompatible, as
// acorn's has a protected constructor
/** @type {unknown} */
(
acorn.Parser.extend(
jsxFactory,
/** @type {(BaseParser: typeof acorn.Parser) => typeof acorn.Parser} */
(espreeParserFactory),
)
)
);
}
return this._jsx;
},
/**
* Gets the parser object based on the supplied options.
* @param {Options} [options] The parser options.
* @returns {EspreeParserJsxCtor|EspreeParserCtor} Regular or JSX Acorn parser
*/
get(options) {
const useJsx = Boolean(
options && options.ecmaFeatures && options.ecmaFeatures.jsx,
);
return useJsx ? this.jsx : this.regular;
},
};
//------------------------------------------------------------------------------
// Tokenizer
//------------------------------------------------------------------------------
/**
* Tokenizes the given code.
* @param {string} code The code to tokenize.
* @param {Options} [options] Options defining how to tokenize.
* @returns {EspreeTokens} An array of tokens.
* @throws {EnhancedSyntaxError} If the input code is invalid.
* @private
*/
export function tokenize(code, options) {
const Parser = parsers.get(options);
// Ensure to collect tokens.
if (!options || options.tokens !== true) {
options = Object.assign({}, options, { tokens: true }); // eslint-disable-line no-param-reassign -- stylistic choice
}
return /** @type {EspreeTokens} */ (new Parser(options, code).tokenize());
}
//------------------------------------------------------------------------------
// Parser
//------------------------------------------------------------------------------
/**
* Parses the given code.
* @param {string} code The code to tokenize.
* @param {Options} [options] Options defining how to tokenize.
* @returns {acorn.Program} The "Program" AST node.
* @throws {EnhancedSyntaxError} If the input code is invalid.
*/
export function parse(code, options) {
const Parser = parsers.get(options);
return new Parser(options, code).parse();
}
//------------------------------------------------------------------------------
// Public
//------------------------------------------------------------------------------
/** @type {string} */
export const version = "11.2.0"; // x-release-please-version
export const name = "espree";
// Derive node types from VisitorKeys
export const Syntax = /* #__PURE__ */ (function () {
let key,
/** @type {Record<string,string>} */
types = {};
if (typeof Object.create === "function") {
types = Object.create(null);
}
for (key in VisitorKeys) {
if (Object.hasOwn(VisitorKeys, key)) {
types[key] = key;
}
}
if (typeof Object.freeze === "function") {
Object.freeze(types);
}
return types;
})();
export const latestEcmaVersion = /* #__PURE__ */ getLatestEcmaVersion();
export const supportedEcmaVersions = /* #__PURE__ */ getSupportedEcmaVersions();
export { KEYS as VisitorKeys } from "eslint-visitor-keys";

View File

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

View File

@@ -0,0 +1,203 @@
'use strict';
const {Readable, Writable, Duplex, Transform} = require('stream');
const none = Symbol.for('object-stream.none');
const finalSymbol = Symbol.for('object-stream.final');
const manySymbol = Symbol.for('object-stream.many');
const final = value => ({[finalSymbol]: value});
const many = values => ({[manySymbol]: values});
const isFinal = o => o && typeof o == 'object' && finalSymbol in o;
const isMany = o => o && typeof o == 'object' && manySymbol in o;
const getFinalValue = o => o[finalSymbol];
const getManyValues = o => o[manySymbol];
const runAsyncGenerator = async (gen, stream) => {
for (;;) {
let data = gen.next();
if (data && typeof data.then == 'function') {
data = await data;
}
if (data.done) break;
let value = data.value;
if (value && typeof value.then == 'function') {
value = await value;
}
Chain.sanitize(value, stream);
}
};
const wrapFunction = fn =>
new Transform({
writableObjectMode: true,
readableObjectMode: true,
transform(chunk, encoding, callback) {
try {
const result = fn.call(this, chunk, encoding);
if (result && typeof result.then == 'function') {
// thenable
result.then(
result => (Chain.sanitize(result, this), callback(null)),
error => callback(error)
);
return;
}
if (result && typeof result.next == 'function') {
// generator
runAsyncGenerator(result, this).then(
() => callback(null),
error => callback(error)
);
return;
}
Chain.sanitize(result, this);
callback(null);
} catch (error) {
callback(error);
}
}
});
const wrapArray = fns =>
new Transform({
writableObjectMode: true,
readableObjectMode: true,
transform(chunk, encoding, callback) {
try {
let value = chunk;
for (let i = 0; i < fns.length; ++i) {
const result = fns[i].call(this, value, encoding);
if (result === Chain.none) {
callback(null);
return;
}
if (Chain.isFinal(result)) {
value = Chain.getFinalValue(result);
break;
}
value = result;
}
Chain.sanitize(value, this);
callback(null);
} catch (error) {
callback(error);
}
}
});
// is*NodeStream functions taken from https://github.com/nodejs/node/blob/master/lib/internal/streams/utils.js
const isReadableNodeStream = obj =>
obj &&
typeof obj.pipe === 'function' &&
typeof obj.on === 'function' &&
(!obj._writableState || (typeof obj._readableState === 'object' ? obj._readableState.readable : null) !== false) && // Duplex
(!obj._writableState || obj._readableState); // Writable has .pipe.
const isWritableNodeStream = obj =>
obj &&
typeof obj.write === 'function' &&
typeof obj.on === 'function' &&
(!obj._readableState || (typeof obj._writableState === 'object' ? obj._writableState.writable : null) !== false); // Duplex
const isDuplexNodeStream = obj =>
obj && typeof obj.pipe === 'function' && obj._readableState && typeof obj.on === 'function' && typeof obj.write === 'function';
class Chain extends Duplex {
constructor(fns, options) {
super(options || {writableObjectMode: true, readableObjectMode: true});
if (!(fns instanceof Array) || !fns.length) {
throw Error("Chain's argument should be a non-empty array.");
}
this.streams = fns
.filter(fn => fn)
.map((fn, index, fns) => {
if (typeof fn === 'function' || fn instanceof Array) return Chain.convertToTransform(fn);
if (isDuplexNodeStream(fn) || (!index && isReadableNodeStream(fn)) || (index === fns.length - 1 && isWritableNodeStream(fn))) {
return fn;
}
throw Error('Arguments should be functions, arrays or streams.');
})
.filter(s => s);
this.input = this.streams[0];
this.output = this.streams.reduce((output, stream) => (output && output.pipe(stream)) || stream);
if (!isWritableNodeStream(this.input)) {
this._write = (_1, _2, callback) => callback(null);
this._final = callback => callback(null); // unavailable in Node 6
this.input.on('end', () => this.end());
}
if (isReadableNodeStream(this.output)) {
this.output.on('data', chunk => !this.push(chunk) && this.output.pause());
this.output.on('end', () => this.push(null));
} else {
this._read = () => {}; // nop
this.resume();
this.output.on('finish', () => this.push(null));
}
// connect events
if (!options || !options.skipEvents) {
this.streams.forEach(stream => stream.on('error', error => this.emit('error', error)));
}
}
_write(chunk, encoding, callback) {
let error = null;
try {
this.input.write(chunk, encoding, e => callback(e || error));
} catch (e) {
error = e;
}
}
_final(callback) {
let error = null;
try {
this.input.end(null, null, e => callback(e || error));
} catch (e) {
error = e;
}
}
_read() {
this.output.resume();
}
static make(fns, options) {
return new Chain(fns, options);
}
static sanitize(result, stream) {
if (Chain.isFinal(result)) {
result = Chain.getFinalValue(result);
} else if (Chain.isMany(result)) {
result = Chain.getManyValues(result);
}
if (result !== undefined && result !== null && result !== Chain.none) {
if (result instanceof Array) {
result.forEach(value => value !== undefined && value !== null && stream.push(value));
} else {
stream.push(result);
}
}
}
static convertToTransform(fn) {
if (typeof fn === 'function') return wrapFunction(fn);
if (fn instanceof Array) return fn.length ? wrapArray(fn) : null;
return null;
}
}
Chain.none = none;
Chain.final = final;
Chain.isFinal = isFinal;
Chain.getFinalValue = getFinalValue;
Chain.many = many;
Chain.isMany = isMany;
Chain.getManyValues = getManyValues;
Chain.chain = Chain.make;
Chain.make.Constructor = Chain;
module.exports = Chain;

View File

@@ -0,0 +1,828 @@
const EventEmitter = require('events').EventEmitter
const utils = require('./utils')
const nodeUtils = require('util')
const sasl = require('./crypto/sasl')
const TypeOverrides = require('./type-overrides')
const ConnectionParameters = require('./connection-parameters')
const Query = require('./query')
const defaults = require('./defaults')
const Connection = require('./connection')
const crypto = require('./crypto/utils')
const activeQueryDeprecationNotice = nodeUtils.deprecate(
() => {},
'Client.activeQuery is deprecated and will be removed in pg@9.0'
)
const queryQueueDeprecationNotice = nodeUtils.deprecate(
() => {},
'Client.queryQueue is deprecated and will be removed in pg@9.0.'
)
const pgPassDeprecationNotice = nodeUtils.deprecate(
() => {},
'pgpass support is deprecated and will be removed in pg@9.0. ' +
'You can provide an async function as the password property to the Client/Pool constructor that returns a password instead. Within this function you can call the pgpass module in your own code.'
)
const byoPromiseDeprecationNotice = nodeUtils.deprecate(
() => {},
'Passing a custom Promise implementation to the Client/Pool constructor is deprecated and will be removed in pg@9.0.'
)
const queryQueueLengthDeprecationNotice = nodeUtils.deprecate(
() => {},
'Calling client.query() when the client is already executing a query is deprecated and will be removed in pg@9.0. Use async/await or an external async flow control mechanism instead.'
)
function coerceNumberOrDefault(value, defaultValue) {
if (typeof value === 'number') {
return Number.isFinite(value) ? value : defaultValue
}
if (typeof value === 'string' && value.trim() !== '') {
const n = Number(value)
return Number.isFinite(n) ? n : defaultValue
}
return defaultValue
}
class Client extends EventEmitter {
constructor(config) {
super()
this.connectionParameters = new ConnectionParameters(config)
this.user = this.connectionParameters.user
this.database = this.connectionParameters.database
this.port = this.connectionParameters.port
this.host = this.connectionParameters.host
// "hiding" the password so it doesn't show up in stack traces
// or if the client is console.logged
Object.defineProperty(this, 'password', {
configurable: true,
enumerable: false,
writable: true,
value: this.connectionParameters.password,
})
this.replication = this.connectionParameters.replication
const c = config || {}
if (c.Promise) {
byoPromiseDeprecationNotice()
}
this._Promise = c.Promise || global.Promise
this._types = new TypeOverrides(c.types)
this._ending = false
this._ended = false
this._connecting = false
this._connected = false
this._connectionError = false
this._queryable = true
this._activeQuery = null
this._txStatus = null
this.enableChannelBinding = Boolean(c.enableChannelBinding) // set true to use SCRAM-SHA-256-PLUS when offered
this.scramMaxIterations = coerceNumberOrDefault(c.scramMaxIterations, sasl.DEFAULT_MAX_SCRAM_ITERATIONS)
this.connection =
c.connection ||
new Connection({
stream: c.stream,
ssl: this.connectionParameters.ssl,
sslNegotiation: this.connectionParameters.sslnegotiation,
keepAlive: c.keepAlive || false,
keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0,
encoding: this.connectionParameters.client_encoding || 'utf8',
})
this._queryQueue = []
this._sentQueryQueue = []
this.pipeline = Boolean(c.pipeline)
this.binary = c.binary || defaults.binary
this.processID = null
this.secretKey = null
this.ssl = this.connectionParameters.ssl || false
this.sslNegotiation = this.connectionParameters.sslnegotiation || 'postgres'
// As with Password, make SSL->Key (the private key) non-enumerable.
// It won't show up in stack traces
// or if the client is console.logged
if (this.ssl && this.ssl.key) {
Object.defineProperty(this.ssl, 'key', {
enumerable: false,
})
}
this._connectionTimeoutMillis = c.connectionTimeoutMillis || 0
}
get activeQuery() {
activeQueryDeprecationNotice()
return this._activeQuery
}
set activeQuery(val) {
activeQueryDeprecationNotice()
this._activeQuery = val
}
_getActiveQuery() {
return this._activeQuery
}
_errorAllQueries(err) {
const enqueueError = (query) => {
process.nextTick(() => {
query.handleError(err, this.connection)
})
}
const activeQuery = this._getActiveQuery()
if (activeQuery) {
enqueueError(activeQuery)
this._activeQuery = null
}
this._sentQueryQueue.forEach(enqueueError)
this._sentQueryQueue.length = 0
this._queryQueue.forEach(enqueueError)
this._queryQueue.length = 0
}
_connect(callback) {
const self = this
const con = this.connection
this._connectionCallback = callback
if (this._connecting || this._connected) {
const err = new Error('Client has already been connected. You cannot reuse a client.')
process.nextTick(() => {
callback(err)
})
return
}
this._connecting = true
if (this._connectionTimeoutMillis > 0) {
this.connectionTimeoutHandle = setTimeout(() => {
con._ending = true
con.stream.destroy(new Error('timeout expired'))
}, this._connectionTimeoutMillis)
if (this.connectionTimeoutHandle.unref) {
this.connectionTimeoutHandle.unref()
}
}
if (this.host && this.host.indexOf('/') === 0) {
con.connect(this.host + '/.s.PGSQL.' + this.port)
} else {
con.connect(this.port, this.host)
}
// once connection is established send startup message
con.on('connect', function () {
if (self.ssl) {
// With direct SSL negotiation the connection upgrades to TLS without an
// SSLRequest packet, so the startup message is sent after 'sslconnect'.
if (self.sslNegotiation !== 'direct') {
con.requestSsl()
}
} else {
con.startup(self.getStartupConf())
}
})
con.on('sslconnect', function () {
con.startup(self.getStartupConf())
})
this._attachListeners(con)
con.once('end', () => {
const error = this._ending ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly')
clearTimeout(this.connectionTimeoutHandle)
this._errorAllQueries(error)
this._ended = true
if (!this._ending) {
// if the connection is ended without us calling .end()
// on this client then we have an unexpected disconnection
// treat this as an error unless we've already emitted an error
// during connection.
if (this._connecting && !this._connectionError) {
if (this._connectionCallback) {
this._connectionCallback(error)
} else {
this._handleErrorEvent(error)
}
} else if (!this._connectionError) {
this._handleErrorEvent(error)
}
}
process.nextTick(() => {
this.emit('end')
})
})
}
connect(callback) {
if (callback) {
this._connect(callback)
return
}
return new this._Promise((resolve, reject) => {
this._connect((error) => {
if (error) {
reject(error)
} else {
resolve(this)
}
})
})
}
_attachListeners(con) {
// password request handling
con.on('authenticationCleartextPassword', this._handleAuthCleartextPassword.bind(this))
// password request handling
con.on('authenticationMD5Password', this._handleAuthMD5Password.bind(this))
// password request handling (SASL)
con.on('authenticationSASL', this._handleAuthSASL.bind(this))
con.on('authenticationSASLContinue', this._handleAuthSASLContinue.bind(this))
con.on('authenticationSASLFinal', this._handleAuthSASLFinal.bind(this))
con.on('backendKeyData', this._handleBackendKeyData.bind(this))
con.on('error', this._handleErrorEvent.bind(this))
con.on('errorMessage', this._handleErrorMessage.bind(this))
con.on('readyForQuery', this._handleReadyForQuery.bind(this))
con.on('notice', this._handleNotice.bind(this))
con.on('rowDescription', this._handleRowDescription.bind(this))
con.on('dataRow', this._handleDataRow.bind(this))
con.on('portalSuspended', this._handlePortalSuspended.bind(this))
con.on('emptyQuery', this._handleEmptyQuery.bind(this))
con.on('commandComplete', this._handleCommandComplete.bind(this))
con.on('parseComplete', this._handleParseComplete.bind(this))
con.on('copyInResponse', this._handleCopyInResponse.bind(this))
con.on('copyData', this._handleCopyData.bind(this))
con.on('notification', this._handleNotification.bind(this))
}
_getPassword(cb) {
const con = this.connection
if (typeof this.password === 'function') {
this._Promise
.resolve()
.then(() => this.password(this.connectionParameters))
.then((pass) => {
if (pass !== undefined) {
if (typeof pass !== 'string') {
con.emit('error', new TypeError('Password must be a string'))
return
}
this.connectionParameters.password = this.password = pass
} else {
this.connectionParameters.password = this.password = null
}
cb()
})
.catch((err) => {
con.emit('error', err)
})
} else if (this.password !== null) {
cb()
} else {
try {
const pgPass = require('pgpass')
pgPass(this.connectionParameters, (pass) => {
if (undefined !== pass) {
pgPassDeprecationNotice()
this.connectionParameters.password = this.password = pass
}
cb()
})
} catch (e) {
this.emit('error', e)
}
}
}
_handleAuthCleartextPassword(msg) {
this._getPassword(() => {
this.connection.password(this.password)
})
}
_handleAuthMD5Password(msg) {
this._getPassword(async () => {
try {
const hashedPassword = await crypto.postgresMd5PasswordHash(this.user, this.password, msg.salt)
this.connection.password(hashedPassword)
} catch (e) {
this.emit('error', e)
}
})
}
_handleAuthSASL(msg) {
this._getPassword(() => {
try {
this.saslSession = sasl.startSession(
msg.mechanisms,
this.enableChannelBinding && this.connection.stream,
this.scramMaxIterations
)
this.connection.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response)
} catch (err) {
this.connection.emit('error', err)
}
})
}
async _handleAuthSASLContinue(msg) {
try {
await sasl.continueSession(
this.saslSession,
this.password,
msg.data,
this.enableChannelBinding && this.connection.stream
)
this.connection.sendSCRAMClientFinalMessage(this.saslSession.response)
} catch (err) {
this.connection.emit('error', err)
}
}
_handleAuthSASLFinal(msg) {
try {
sasl.finalizeSession(this.saslSession, msg.data)
this.saslSession = null
} catch (err) {
this.connection.emit('error', err)
}
}
_handleBackendKeyData(msg) {
this.processID = msg.processID
this.secretKey = msg.secretKey
}
_handleReadyForQuery(msg) {
if (this._connecting) {
this._connecting = false
this._connected = true
clearTimeout(this.connectionTimeoutHandle)
// process possible callback argument to Client#connect
if (this._connectionCallback) {
this._connectionCallback(null, this)
// remove callback for proper error handling
// after the connect event
this._connectionCallback = null
}
this.emit('connect')
}
const activeQuery = this._getActiveQuery()
this._activeQuery = null
this._txStatus = msg?.status ?? null
this.readyForQuery = true
if (activeQuery) {
activeQuery.handleReadyForQuery(this.connection)
}
this._pulseQueryQueue()
}
// if we receive an error event or error message
// during the connection process we handle it here
_handleErrorWhileConnecting(err) {
if (this._connectionError) {
// TODO(bmc): this is swallowing errors - we shouldn't do this
return
}
this._connectionError = true
clearTimeout(this.connectionTimeoutHandle)
if (this._connectionCallback) {
return this._connectionCallback(err)
}
this.emit('error', err)
}
// if we're connected and we receive an error event from the connection
// this means the socket is dead - do a hard abort of all queries and emit
// the socket error on the client as well
_handleErrorEvent(err) {
if (this._connecting) {
return this._handleErrorWhileConnecting(err)
}
this._queryable = false
this._errorAllQueries(err)
this.emit('error', err)
}
// handle error messages from the postgres backend
_handleErrorMessage(msg) {
if (this._connecting) {
return this._handleErrorWhileConnecting(msg)
}
const activeQuery = this._getActiveQuery()
if (!activeQuery) {
this._handleErrorEvent(msg)
return
}
this._activeQuery = null
if (activeQuery.name) {
delete this.connection.submittedNamedStatements[activeQuery.name]
}
activeQuery.handleError(msg, this.connection)
}
_handleRowDescription(msg) {
const activeQuery = this._getActiveQuery()
if (activeQuery == null) {
const error = new Error('Received unexpected rowDescription message from backend.')
this._handleErrorEvent(error)
return
}
// delegate rowDescription to active query
activeQuery.handleRowDescription(msg)
}
_handleDataRow(msg) {
const activeQuery = this._getActiveQuery()
if (activeQuery == null) {
const error = new Error('Received unexpected dataRow message from backend.')
this._handleErrorEvent(error)
return
}
// delegate dataRow to active query
activeQuery.handleDataRow(msg)
}
_handlePortalSuspended(msg) {
const activeQuery = this._getActiveQuery()
if (activeQuery == null) {
const error = new Error('Received unexpected portalSuspended message from backend.')
this._handleErrorEvent(error)
return
}
// delegate portalSuspended to active query
activeQuery.handlePortalSuspended(this.connection)
}
_handleEmptyQuery(msg) {
const activeQuery = this._getActiveQuery()
if (activeQuery == null) {
const error = new Error('Received unexpected emptyQuery message from backend.')
this._handleErrorEvent(error)
return
}
// delegate emptyQuery to active query
activeQuery.handleEmptyQuery(this.connection)
}
_handleCommandComplete(msg) {
const activeQuery = this._getActiveQuery()
if (activeQuery == null) {
const error = new Error('Received unexpected commandComplete message from backend.')
this._handleErrorEvent(error)
return
}
// delegate commandComplete to active query
activeQuery.handleCommandComplete(msg, this.connection)
}
_handleParseComplete() {
const activeQuery = this._getActiveQuery()
if (activeQuery == null) {
const error = new Error('Received unexpected parseComplete message from backend.')
this._handleErrorEvent(error)
return
}
// if a prepared statement has a name and properly parses
// we track that its already been executed so we don't parse
// it again on the same client
if (activeQuery.name) {
this.connection.parsedStatements[activeQuery.name] = activeQuery.text
delete this.connection.submittedNamedStatements[activeQuery.name]
}
}
_handleCopyInResponse(msg) {
const activeQuery = this._getActiveQuery()
if (activeQuery == null) {
const error = new Error('Received unexpected copyInResponse message from backend.')
this._handleErrorEvent(error)
return
}
activeQuery.handleCopyInResponse(this.connection)
}
_handleCopyData(msg) {
const activeQuery = this._getActiveQuery()
if (activeQuery == null) {
const error = new Error('Received unexpected copyData message from backend.')
this._handleErrorEvent(error)
return
}
activeQuery.handleCopyData(msg, this.connection)
}
_handleNotification(msg) {
this.emit('notification', msg)
}
_handleNotice(msg) {
this.emit('notice', msg)
}
getStartupConf() {
const params = this.connectionParameters
const data = {
user: params.user,
database: params.database,
}
const appName = params.application_name || params.fallback_application_name
if (appName) {
data.application_name = appName
}
if (params.replication) {
data.replication = '' + params.replication
}
if (params.statement_timeout) {
data.statement_timeout = String(parseInt(params.statement_timeout, 10))
}
if (params.lock_timeout) {
data.lock_timeout = String(parseInt(params.lock_timeout, 10))
}
if (params.idle_in_transaction_session_timeout) {
data.idle_in_transaction_session_timeout = String(parseInt(params.idle_in_transaction_session_timeout, 10))
}
if (params.options) {
data.options = params.options
}
return data
}
cancel(client, query) {
if (client.activeQuery === query) {
const con = this.connection
if (this.host && this.host.indexOf('/') === 0) {
con.connect(this.host + '/.s.PGSQL.' + this.port)
} else {
con.connect(this.port, this.host)
}
// once connection is established send cancel message
con.on('connect', function () {
con.cancel(client.processID, client.secretKey)
})
} else if (client._queryQueue.indexOf(query) !== -1) {
client._queryQueue.splice(client._queryQueue.indexOf(query), 1)
} else if (client._sentQueryQueue.indexOf(query) !== -1) {
// Query already sent on wire — can't remove it without corrupting the
// pipeline. No-op the callback so the result is silently discarded.
query.callback = () => {}
}
}
setTypeParser(oid, format, parseFn) {
return this._types.setTypeParser(oid, format, parseFn)
}
getTypeParser(oid, format) {
return this._types.getTypeParser(oid, format)
}
// escapeIdentifier and escapeLiteral moved to utility functions & exported
// on PG
// re-exported here for backwards compatibility
escapeIdentifier(str) {
return utils.escapeIdentifier(str)
}
escapeLiteral(str) {
return utils.escapeLiteral(str)
}
_pulseQueryQueue() {
if (this.pipeline) {
this._pulsePipelinedQueryQueue()
return
}
if (this.readyForQuery === true) {
this._activeQuery = this._queryQueue.shift()
const activeQuery = this._getActiveQuery()
if (activeQuery) {
this.readyForQuery = false
this.hasExecuted = true
const queryError = activeQuery.submit(this.connection)
if (queryError) {
process.nextTick(() => {
activeQuery.handleError(queryError, this.connection)
this.readyForQuery = true
this._pulseQueryQueue()
})
}
} else if (this.hasExecuted) {
this._activeQuery = null
this.emit('drain')
}
}
}
_pulsePipelinedQueryQueue() {
if (!this._connected || !this._queryable) {
return
}
while (this._queryQueue.length > 0) {
const query = this._queryQueue.shift()
this.hasExecuted = true
const queryError = query.submit(this.connection)
if (queryError) {
process.nextTick(() => {
query.handleError(queryError, this.connection)
})
continue
}
this._sentQueryQueue.push(query)
}
if (this.readyForQuery && !this._activeQuery && this._sentQueryQueue.length > 0) {
this._activeQuery = this._sentQueryQueue.shift()
this.readyForQuery = false
}
if (!this._activeQuery && this._sentQueryQueue.length === 0 && this._queryQueue.length === 0 && this.hasExecuted) {
this.emit('drain')
}
}
query(config, values, callback) {
// can take in strings, config object or query object
let query
let result
if (config == null) {
throw new TypeError('Client was passed a null or undefined query')
}
if (typeof config.submit === 'function') {
result = query = config
if (!query.callback) {
if (typeof values === 'function') {
query.callback = values
} else if (callback) {
query.callback = callback
}
}
} else {
query = new Query(config, values, callback)
if (!query.callback) {
result = new this._Promise((resolve, reject) => {
query.callback = (err, res) => (err ? reject(err) : resolve(res))
}).catch((err) => {
// replace the stack trace that leads to `TCP.onStreamRead` with one that leads back to the
// application that created the query
Error.captureStackTrace(err)
throw err
})
} else if (typeof query.callback !== 'function') {
throw new TypeError('callback is not a function')
}
}
const readTimeout = config.query_timeout || this.connectionParameters.query_timeout
if (readTimeout) {
const queryCallback = query.callback || (() => {})
const readTimeoutTimer = setTimeout(() => {
const error = new Error('Query read timeout')
process.nextTick(() => {
query.handleError(error, this.connection)
})
queryCallback(error)
// we already returned an error,
// just do nothing if query completes
query.callback = () => {}
// Remove from queue (only safe if not yet sent)
const index = this._queryQueue.indexOf(query)
if (index > -1) {
this._queryQueue.splice(index, 1)
} else if (this.pipeline) {
// Query already sent — the pipeline is blocked until it completes.
// Destroy the connection to unblock all remaining pipelined queries.
this.connection.stream.destroy()
return
}
this._pulseQueryQueue()
}, readTimeout)
query.callback = (err, res) => {
clearTimeout(readTimeoutTimer)
queryCallback(err, res)
}
}
if (this.binary && !query.binary) {
query.binary = true
}
if (query._result && !query._result._types) {
query._result._types = this._types
}
if (!this._queryable) {
process.nextTick(() => {
query.handleError(new Error('Client has encountered a connection error and is not queryable'), this.connection)
})
return result
}
if (this._ending) {
process.nextTick(() => {
query.handleError(new Error('Client was closed and is not queryable'), this.connection)
})
return result
}
if (this._queryQueue.length > 0 && !this.pipeline) {
queryQueueLengthDeprecationNotice()
}
this._queryQueue.push(query)
this._pulseQueryQueue()
return result
}
ref() {
this.connection.ref()
}
unref() {
this.connection.unref()
}
getTransactionStatus() {
return this._txStatus
}
end(cb) {
this._ending = true
// if we have never connected, then end is a noop, callback immediately
if (!this.connection._connecting || this._ended) {
if (cb) {
cb()
return
} else {
return this._Promise.resolve()
}
}
if (!this._queryable) {
// socket is dead — force close
this.connection.stream.destroy()
} else if (
this.pipeline &&
(this._getActiveQuery() || this._sentQueryQueue.length > 0 || this._queryQueue.length > 0)
) {
// pipelined queries are already on the wire (or queued to send) and will
// complete normally; wait for drain then do a graceful goodbye
this.once('drain', () => this.connection.end())
} else if (this._getActiveQuery()) {
// non-pipeline: a hung query could block end forever — force disconnect
this.connection.stream.destroy()
} else {
this.connection.end()
}
if (cb) {
this.connection.once('end', cb)
} else {
return new this._Promise((resolve) => {
this.connection.once('end', resolve)
})
}
}
get queryQueue() {
queryQueueDeprecationNotice()
return this._queryQueue
}
}
// expose a Query constructor
Client.Query = Query
module.exports = Client

View File

@@ -0,0 +1,10 @@
export type Options = [
{
ignoreStringArrays?: boolean;
}
];
export type MessageIds = 'requireCompare';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"requireCompare", Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
name: string;
};
export default _default;

View File

@@ -0,0 +1,48 @@
'use strict'
const parse = require('./parse')
const constants = require('../internal/constants')
const SemVer = require('../classes/semver')
const truncate = (version, truncation, options) => {
if (!constants.RELEASE_TYPES.includes(truncation)) {
return null
}
const clonedVersion = cloneInputVersion(version, options)
return clonedVersion && doTruncation(clonedVersion, truncation)
}
const cloneInputVersion = (version, options) => {
const versionStringToParse = (
version instanceof SemVer ? version.version : version
)
return parse(versionStringToParse, options)
}
const doTruncation = (version, truncation) => {
if (isPrerelease(truncation)) {
return version.version
}
version.prerelease = []
switch (truncation) {
case 'major':
version.minor = 0
version.patch = 0
break
case 'minor':
version.patch = 0
break
}
return version.format()
}
const isPrerelease = (type) => {
return type.startsWith('pre')
}
module.exports = truncate

View File

@@ -0,0 +1,25 @@
import './types.d-BjI5eAwu.js';
type Key = string | symbol;
type CreateMockInstanceProcedure = (options?: {
prototypeMembers?: (string | symbol)[];
name?: string | symbol;
originalImplementation?: (...args: any[]) => any;
keepMembersImplementation?: boolean;
}) => any;
interface MockObjectOptions {
type: "automock" | "autospy";
globalConstructors: GlobalConstructors;
createMockInstance: CreateMockInstanceProcedure;
}
declare function mockObject(options: MockObjectOptions, object: Record<Key, any>, mockExports?: Record<Key, any>): Record<Key, any>;
interface GlobalConstructors {
Object: ObjectConstructor;
Function: FunctionConstructor;
RegExp: RegExpConstructor;
Array: ArrayConstructor;
Map: MapConstructor;
}
export { mockObject as m };
export type { CreateMockInstanceProcedure as C, GlobalConstructors as G, MockObjectOptions as M };

View File

@@ -0,0 +1,192 @@
'use strict'
const { format } = require('node:util')
/**
* @namespace processWarning
*/
/**
* Represents a warning item with details.
* @typedef {Function} WarningItem
* @param {*} [a] Possible message interpolation value.
* @param {*} [b] Possible message interpolation value.
* @param {*} [c] Possible message interpolation value.
* @property {string} name - The name of the warning.
* @property {string} code - The code associated with the warning.
* @property {string} message - The warning message.
* @property {boolean} emitted - Indicates if the warning has been emitted.
* @property {function} format - Formats the warning message.
* @returns {boolean} emit - Indicates if the warning has been emitted by this call.
*/
/**
* Options for creating a process warning.
* @typedef {Object} ProcessWarningOptions
* @property {string} name - The name of the warning.
* @property {string} code - The code associated with the warning.
* @property {string} message - The warning message.
* @property {boolean} [unlimited=false] - If true, allows unlimited emissions of the warning.
*/
/**
* Represents the process warning functionality.
* @typedef {Object} ProcessWarning
* @property {function} createWarning - Creates a warning item.
* @property {function} createDeprecation - Creates a deprecation warning item.
* @property {function} spyWarning - Spy a warning item.
*/
/**
* Represents the spy data.
* @typedef {Object} WarningSpyData
* @property {object} calls - Arguments of WarningItem calls with.
* @property {function} callCount - Number of counts called the WarningItem.
* @property {function} reset - Reset the calls data and state of WarningItem.
* @property {function} restore - Remove spy from WarningItem.
*/
const kWarningFn = Symbol('process-warning.fn')
const kWarningSpyData = Symbol('process-warning.spyData')
/**
* Spy a warning item.
* @function
* @memberof processWarning
* @param {WarningItem} warning - The warning item to spy.
* @returns {WarningSpyData} The created spy data.
*/
function spyWarning (warning) {
// Do not double spy the same warning
if (warning[kWarningSpyData] === null) {
const warningFn = warning[kWarningFn]
warning[kWarningFn] = function (a, b, c) {
const args = []
// since warning always call by fn(a, b, c)
// it need to remove the trailing undefined arguments
if (c) {
args.push(a, b, c)
} else if (b) {
args.push(a, b)
} else if (a) {
args.push(a)
}
warning[kWarningSpyData].calls.push({
arguments: args,
result: warningFn(a, b, c)
})
}
const spyData = {
calls: [],
callCount () {
return spyData.calls.length
},
reset () {
warning.emitted = false
spyData.calls.length = 0
},
restore () {
spyData.reset()
warning[kWarningFn] = warningFn
warning[kWarningSpyData] = null
}
}
warning[kWarningSpyData] = spyData
}
return warning[kWarningSpyData]
}
/**
* Creates a deprecation warning item.
* @function
* @memberof processWarning
* @param {ProcessWarningOptions} params - Options for creating the warning.
* @returns {WarningItem} The created deprecation warning item.
*/
function createDeprecation (params) {
return createWarning({ ...params, name: 'DeprecationWarning' })
}
/**
* Creates a warning item.
* @function
* @memberof processWarning
* @param {ProcessWarningOptions} params - Options for creating the warning.
* @returns {WarningItem} The created warning item.
* @throws {Error} Throws an error if name, code, or message is empty, or if opts.unlimited is not a boolean.
*/
function createWarning ({ name, code, message, unlimited = false } = {}) {
if (!name) throw new Error('Warning name must not be empty')
if (!code) throw new Error('Warning code must not be empty')
if (!message) throw new Error('Warning message must not be empty')
if (typeof unlimited !== 'boolean') throw new Error('Warning opts.unlimited must be a boolean')
code = code.toUpperCase()
const warningFn = unlimited === true
? function (a, b, c) {
warning.emitted = true
process.emitWarning(warning.format(a, b, c), warning.name, warning.code)
return true
}
: function (a, b, c) {
if (warning.emitted === true && warning.unlimited !== true) {
return false
}
warning.emitted = true
process.emitWarning(warning.format(a, b, c), warning.name, warning.code)
return true
}
const warningContainer = {
[name]: function (a, b, c) {
return warning[kWarningFn](a, b, c)
}
}
const warning = warningContainer[name]
warning.emitted = false
warning.message = message
warning.unlimited = unlimited
warning.code = code
warning[kWarningFn] = warningFn
warning[kWarningSpyData] = null
/**
* Formats the warning message.
* @param {*} [a] Possible message interpolation value.
* @param {*} [b] Possible message interpolation value.
* @param {*} [c] Possible message interpolation value.
* @returns {string} The formatted warning message.
*/
warning.format = function (a, b, c) {
let formatted
if (a && b && c) {
formatted = format(message, a, b, c)
} else if (a && b) {
formatted = format(message, a, b)
} else if (a) {
formatted = format(message, a)
} else {
formatted = message
}
return formatted
}
return warning
}
/**
* Module exports containing the process warning functionality.
* @namespace
* @property {function} createWarning - Creates a warning item.
* @property {function} createDeprecation - Creates a deprecation warning item.
* @property {function} spyWarning - Spy a warning item.
* @property {ProcessWarning} processWarning - Represents the process warning functionality.
*/
const out = { createWarning, createDeprecation, spyWarning }
module.exports = out
module.exports.default = out
module.exports.processWarning = out

View File

@@ -0,0 +1,72 @@
import { expect, test } from "vitest";
import { z } from "../../../../index.js";
import fr from "../../../locales/fr.js";
test("French locale - type name translations in too_small errors", () => {
z.config(fr());
const stringResult = z.string().min(5).safeParse("abc");
expect(stringResult.success).toBe(false);
if (!stringResult.success) {
expect(stringResult.error.issues[0].message).toBe("Trop petit : chaîne doit avoir >=5 caractères");
}
const numberResult = z.number().min(10).safeParse(5);
expect(numberResult.success).toBe(false);
if (!numberResult.success) {
expect(numberResult.error.issues[0].message).toBe("Trop petit : nombre doit être >=10");
}
const arrayResult = z.array(z.string()).min(3).safeParse(["a", "b"]);
expect(arrayResult.success).toBe(false);
if (!arrayResult.success) {
expect(arrayResult.error.issues[0].message).toBe("Trop petit : tableau doit avoir >=3 éléments");
}
const setResult = z
.set(z.string())
.min(2)
.safeParse(new Set(["a"]));
expect(setResult.success).toBe(false);
if (!setResult.success) {
expect(setResult.error.issues[0].message).toBe("Trop petit : ensemble doit avoir >=2 éléments");
}
});
test("French locale - type name translations in too_big errors", () => {
z.config(fr());
const stringResult = z.string().max(3).safeParse("abcde");
expect(stringResult.success).toBe(false);
if (!stringResult.success) {
expect(stringResult.error.issues[0].message).toBe("Trop grand : chaîne doit avoir <=3 caractères");
}
const numberResult = z.number().max(10).safeParse(15);
expect(numberResult.success).toBe(false);
if (!numberResult.success) {
expect(numberResult.error.issues[0].message).toBe("Trop grand : nombre doit être <=10");
}
const arrayResult = z.array(z.string()).max(2).safeParse(["a", "b", "c"]);
expect(arrayResult.success).toBe(false);
if (!arrayResult.success) {
expect(arrayResult.error.issues[0].message).toBe("Trop grand : tableau doit avoir <=2 éléments");
}
});
test("French locale - type name translations in invalid_type errors", () => {
z.config(fr());
const stringResult = z.string().safeParse(123);
expect(stringResult.success).toBe(false);
if (!stringResult.success) {
expect(stringResult.error.issues[0].message).toBe("Entrée invalide : chaîne attendu, nombre reçu");
}
const arrayResult = z.array(z.string()).safeParse({});
expect(arrayResult.success).toBe(false);
if (!arrayResult.success) {
expect(arrayResult.error.issues[0].message).toBe("Entrée invalide : tableau attendu, objet reçu");
}
});

View File

@@ -0,0 +1,309 @@
# Acorn
A tiny, fast JavaScript parser written in JavaScript.
## Community
Acorn is open source software released under an
[MIT license](https://github.com/acornjs/acorn/blob/master/acorn/LICENSE).
You are welcome to
[report bugs](https://github.com/acornjs/acorn/issues) or create pull
requests on [github](https://github.com/acornjs/acorn).
## Installation
The easiest way to install acorn is from [`npm`](https://www.npmjs.com/):
```sh
npm install acorn
```
Alternately, you can download the source and build acorn yourself:
```sh
git clone https://github.com/acornjs/acorn.git
cd acorn
npm install
```
## Importing acorn
ESM as well as CommonJS is supported for all 3: `acorn`, `acorn-walk` and `acorn-loose`.
ESM example for `acorn`:
```js
import * as acorn from "acorn"
```
CommonJS example for `acorn`:
```js
let acorn = require("acorn")
```
ESM is preferred, as it allows better editor auto-completions by offering TypeScript support.
For this reason, following examples will use ESM imports.
## Interface
**parse**`(input, options)` is the main interface to the library. The
`input` parameter is a string, `options` must be an object setting
some of the options listed below. The return value will be an abstract
syntax tree object as specified by the [ESTree
spec](https://github.com/estree/estree).
```javascript
import * as acorn from "acorn"
console.log(acorn.parse("1 + 1", {ecmaVersion: 2020}))
```
When encountering a syntax error, the parser will raise a
`SyntaxError` object with a meaningful message. The error object will
have a `pos` property that indicates the string offset at which the
error occurred, and a `loc` object that contains a `{line, column}`
object referring to that same position.
Options are provided by in a second argument, which should be an
object containing any of these fields (only `ecmaVersion` is
required):
- **ecmaVersion**: Indicates the ECMAScript version to parse. Can be a
number, either in year (`2022`) or plain version number (`6`) form,
or `"latest"` (the latest the library supports). This influences
support for strict mode, the set of reserved words, and support for
new syntax features.
**NOTE**: Only 'stage 4' (finalized) ECMAScript features are being
implemented by Acorn. Other proposed new features must be
implemented through plugins.
- **sourceType**: Indicate the mode the code should be parsed in. Can be
either `"script"`, `"module"` or `"commonjs"`. This influences global strict mode
and parsing of `import` and `export` declarations.
**NOTE**: If set to `"module"`, then static `import` / `export` syntax
will be valid, even if `ecmaVersion` is less than 6. If set to `"commonjs"`,
it is the same as `"script"` except that the top-level scope behaves like a function.
- **strict**: When set to true, enable strict parsing mode even if
`sourceType` is `"script"`.
- **onInsertedSemicolon**: If given a callback, that callback will be
called whenever a missing semicolon is inserted by the parser. The
callback will be given the character offset of the point where the
semicolon is inserted as argument, and if `locations` is on, also a
`{line, column}` object representing this position.
- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing
commas.
- **allowReserved**: If `false`, using a reserved word will generate
an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher
versions. When given the value `"never"`, reserved words and
keywords can also not be used as property names (as in Internet
Explorer's old parser).
- **allowReturnOutsideFunction**: By default, a return statement at
the top level raises an error. Set this to `true` to accept such
code.
- **allowImportExportEverywhere**: By default, `import` and `export`
declarations can only appear at a program's top level. Setting this
option to `true` allows them anywhere where a statement is allowed,
and also allows `import.meta` expressions to appear in scripts
(when `sourceType` is not `"module"`).
- **allowAwaitOutsideFunction**: If `false`, `await` expressions can
only appear inside `async` functions. Defaults to `true` in modules
for `ecmaVersion` 2022 and later, `false` for lower versions.
Setting this option to `true` allows to have top-level `await`
expressions. They are still not allowed in non-`async` functions,
though. Setting this option to `true` is not allowed when `sourceType: "commonjs"`.
- **allowSuperOutsideMethod**: By default, `super` outside a method
raises an error. Set this to `true` to accept such code.
- **allowHashBang**: When this is enabled, if the code starts with the
characters `#!` (as in a shellscript), the first line will be
treated as a comment. Defaults to true when `ecmaVersion` >= 2023.
- **checkPrivateFields**: By default, the parser will verify that
private properties are only used in places where they are valid and
have been declared. Set this to false to turn such checks off.
- **locations**: When `true`, each node has a `loc` object attached
with `start` and `end` subobjects, each of which contains the
one-based line and zero-based column numbers in `{line, column}`
form. Default is `false`.
- **startLocation**: An optional `{line, column}` object to use for
the start of the parse. This is mostly useful when using
`parseExpressionAt` with `locations: true`, to prevent the parser
from having to determine the line position at the start position.
- **onToken**: If a function is passed for this option, each found
token will be passed in same format as tokens returned from
`tokenizer().getToken()`.
If array is passed, each found token is pushed to it.
Note that you are not allowed to call the parser from the
callback—that will corrupt its internal state.
- **onComment**: If a function is passed for this option, whenever a
comment is encountered the function will be called with the
following parameters:
- `block`: `true` if the comment is a block comment, false if it
is a line comment.
- `text`: The content of the comment.
- `start`: Character offset of the start of the comment.
- `end`: Character offset of the end of the comment.
When the `locations` options is on, the `{line, column}` locations
of the comments start and end are passed as two additional
parameters.
If array is passed for this option, each found comment is pushed
to it as object in Esprima format:
```javascript
{
"type": "Line" | "Block",
"value": "comment text",
"start": Number,
"end": Number,
// If `locations` option is on:
"loc": {
"start": {line: Number, column: Number}
"end": {line: Number, column: Number}
},
// If `ranges` option is on:
"range": [Number, Number]
}
```
Note that you are not allowed to call the parser from the
callback—that will corrupt its internal state.
- **ranges**: Nodes have their start and end characters offsets
recorded in `start` and `end` properties (directly on the node,
rather than the `loc` object, which holds line/column data. To also
add a
[semi-standardized](https://bugzilla.mozilla.org/show_bug.cgi?id=745678)
`range` property holding a `[start, end]` array with the same
numbers, set the `ranges` option to `true`.
- **program**: It is possible to parse multiple files into a single
AST by passing the tree produced by parsing the first file as the
`program` option in subsequent parses. This will add the toplevel
forms of the parsed file to the "Program" (top) node of an existing
parse tree.
- **sourceFile**: When the `locations` option is `true`, you can pass
this option to add a `source` attribute in every nodes `loc`
object. Note that the contents of this option are not examined or
processed in any way; you are free to use whatever format you
choose.
- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property
will be added (regardless of the `location` option) directly to the
nodes, rather than the `loc` object.
- **preserveParens**: If this option is `true`, parenthesized expressions
are represented by (non-standard) `ParenthesizedExpression` nodes
that have a single `expression` property containing the expression
inside parentheses.
**parseExpressionAt**`(input, offset, options)` will parse a single
expression in a string, and return its AST. It will not complain if
there is more of the string left after the expression.
**tokenizer**`(input, options)` returns an object with a `getToken`
method that can be called repeatedly to get the next token, a `{start,
end, type, value}` object (with added `loc` property when the
`locations` option is enabled and `range` property when the `ranges`
option is enabled). When the token's type is `tokTypes.eof`, you
should stop calling the method, since it will keep returning that same
token forever.
Note that tokenizing JavaScript without parsing it is, in modern
versions of the language, not really possible due to the way syntax is
overloaded in ways that can only be disambiguated by the parse
context. This package applies a bunch of heuristics to try and do a
reasonable job, but you are advised to use `parse` with the `onToken`
option instead of this.
In ES6 environment, returned result can be used as any other
protocol-compliant iterable:
```javascript
for (let token of acorn.tokenizer(str)) {
// iterate over the tokens
}
// transform code to array of tokens:
var tokens = [...acorn.tokenizer(str)]
```
**tokTypes** holds an object mapping names to the token type objects
that end up in the `type` properties of tokens.
**getLineInfo**`(input, offset)` can be used to get a `{line,
column}` object for a given program string and offset.
### The `Parser` class
Instances of the **`Parser`** class contain all the state and logic
that drives a parse. It has static methods `parse`,
`parseExpressionAt`, and `tokenizer` that match the top-level
functions by the same name.
When extending the parser with plugins, you need to call these methods
on the extended version of the class. To extend a parser with plugins,
you can use its static `extend` method.
```javascript
var acorn = require("acorn")
var jsx = require("acorn-jsx")
var JSXParser = acorn.Parser.extend(jsx())
JSXParser.parse("foo(<bar/>)", {ecmaVersion: 2020})
```
The `extend` method takes any number of plugin values, and returns a
new `Parser` class that includes the extra parser logic provided by
the plugins.
## Command line interface
The `bin/acorn` utility can be used to parse a file from the command
line. It accepts as arguments its input file and the following
options:
- `--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|--ecma10`: Sets the ECMAScript version
to parse. Default is version 9.
- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise.
- `--locations`: Attaches a "loc" object to each node with "start" and
"end" subobjects, each of which contains the one-based line and
zero-based column numbers in `{line, column}` form.
- `--allow-hash-bang`: If the code starts with the characters #! (as
in a shellscript), the first line will be treated as a comment.
- `--allow-await-outside-function`: Allows top-level `await` expressions.
See the `allowAwaitOutsideFunction` option for more information.
- `--compact`: No whitespace is used in the AST output.
- `--silent`: Do not output the AST, just return the exit status.
- `--help`: Print the usage information and quit.
The utility spits out the syntax tree as JSON data.
## Existing plugins
- [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx)

View File

@@ -0,0 +1,15 @@
/**
* Internal webcrypto alias.
* We prefer WebCrypto aka globalThis.crypto, which exists in node.js 16+.
* Falls back to Node.js built-in crypto for Node.js <=v14.
* See utils.ts for details.
* @module
*/
// @ts-ignore
import * as nc from 'node:crypto';
export const crypto = nc && typeof nc === 'object' && 'webcrypto' in nc
? nc.webcrypto
: nc && typeof nc === 'object' && 'randomBytes' in nc
? nc
: undefined;
//# sourceMappingURL=cryptoNode.js.map

View File

@@ -0,0 +1,11 @@
"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.webworker_asynciterable = void 0;
exports.webworker_asynciterable = {
libs: [],
variables: [],
};

View File

@@ -0,0 +1,14 @@
'use strict';
module.exports = function generate_comment(it, $keyword, $ruleType) {
var out = ' ';
var $schema = it.schema[$keyword];
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $comment = it.util.toQuotedString($schema);
if (it.opts.$comment === true) {
out += ' console.log(' + ($comment) + ');';
} else if (typeof it.opts.$comment == 'function') {
out += ' self._opts.$comment(' + ($comment) + ', ' + (it.util.toQuotedString($errSchemaPath)) + ', validate.root.schema);';
}
return out;
}

View File

@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const util_1 = require("../util");
const getESLintCoreRule_1 = require("../util/getESLintCoreRule");
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-unused-expressions');
const defaultOptions = [
{
allowShortCircuit: false,
allowTaggedTemplates: false,
allowTernary: false,
},
];
exports.default = (0, util_1.createRule)({
name: 'no-unused-expressions',
meta: {
type: 'suggestion',
defaultOptions,
docs: {
description: 'Disallow unused expressions',
extendsBaseRule: true,
recommended: 'recommended',
},
hasSuggestions: baseRule.meta.hasSuggestions,
messages: baseRule.meta.messages,
schema: baseRule.meta.schema,
},
defaultOptions,
create(context, [{ allowShortCircuit = false, allowTernary = false }]) {
const rules = baseRule.create(context);
function isValidExpression(node) {
if (allowShortCircuit && node.type === utils_1.AST_NODE_TYPES.LogicalExpression) {
return isValidExpression(node.right);
}
if (allowTernary && node.type === utils_1.AST_NODE_TYPES.ConditionalExpression) {
return (isValidExpression(node.alternate) &&
isValidExpression(node.consequent));
}
return ((node.type === utils_1.AST_NODE_TYPES.ChainExpression &&
node.expression.type === utils_1.AST_NODE_TYPES.CallExpression) ||
node.type === utils_1.AST_NODE_TYPES.ImportExpression);
}
return {
ExpressionStatement(node) {
if (node.directive || isValidExpression(node.expression)) {
return;
}
const expressionType = node.expression.type;
if (expressionType ===
utils_1.TSESTree.AST_NODE_TYPES.TSInstantiationExpression ||
expressionType === utils_1.TSESTree.AST_NODE_TYPES.TSAsExpression ||
expressionType === utils_1.TSESTree.AST_NODE_TYPES.TSNonNullExpression ||
expressionType === utils_1.TSESTree.AST_NODE_TYPES.TSTypeAssertion) {
rules.ExpressionStatement({
...node,
expression: node.expression.expression,
});
return;
}
rules.ExpressionStatement(node);
},
};
},
});

View File

@@ -0,0 +1,8 @@
function _isNativeFunction(t) {
try {
return -1 !== Function.toString.call(t).indexOf("[native code]");
} catch (n) {
return "function" == typeof t;
}
}
module.exports = _isNativeFunction, module.exports.__esModule = true, module.exports["default"] = module.exports;

View File

@@ -0,0 +1,374 @@
import { expect, test } from "vitest";
import * as z from "zod/v4";
test("continuability", () => {
/**
* | $ZodGUID
| $ZodUUID
| $ZodEmail
| $ZodURL
| $ZodEmoji
| $ZodNanoID
| $ZodCUID
| $ZodCUID2
| $ZodULID
| $ZodXID
| $ZodKSUID
| $ZodISODateTime
| $ZodISODate
| $ZodISOTime
| $ZodISODuration
| $ZodIPv4
| $ZodIPv6
| $ZodCIDRv4
| $ZodCIDRv6
| $ZodBase64
| $ZodBase64URL
| $ZodE164
| $ZodJWT;
*/
expect(
z
.email()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "email",
"message": "Invalid email address",
"origin": "string",
"path": [],
"pattern": "/^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.uuid()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "uuid",
"message": "Invalid UUID",
"origin": "string",
"path": [],
"pattern": "/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.url()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "url",
"message": "Invalid URL",
"path": [],
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.jwt()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "jwt",
"message": "Invalid JWT",
"path": [],
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.cidrv4()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "cidrv4",
"message": "Invalid IPv4 range",
"origin": "string",
"path": [],
"pattern": "/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/([0-9]|[1-2][0-9]|3[0-2])$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.cidrv6()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "cidrv6",
"message": "Invalid IPv6 range",
"path": [],
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.ipv4()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "ipv4",
"message": "Invalid IPv4 address",
"origin": "string",
"path": [],
"pattern": "/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.ipv6()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "ipv6",
"message": "Invalid IPv6 address",
"path": [],
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.mac()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "mac",
"message": "Invalid MAC address",
"origin": "string",
"path": [],
"pattern": "/^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.emoji()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "emoji",
"message": "Invalid emoji",
"origin": "string",
"path": [],
"pattern": "/^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$/u",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.nanoid()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "nanoid",
"message": "Invalid nanoid",
"origin": "string",
"path": [],
"pattern": "/^[a-zA-Z0-9_-]{21}$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.cuid()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "cuid",
"message": "Invalid cuid",
"origin": "string",
"path": [],
"pattern": "/^[cC][0-9a-z]{6,}$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.cuid2()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "cuid2",
"message": "Invalid cuid2",
"origin": "string",
"path": [],
"pattern": "/^[0-9a-z]+$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.ulid()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "ulid",
"message": "Invalid ULID",
"origin": "string",
"path": [],
"pattern": "/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.xid()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "xid",
"message": "Invalid XID",
"origin": "string",
"path": [],
"pattern": "/^[0-9a-vA-V]{20}$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
expect(
z
.ksuid()
.refine(() => false)
.safeParse("invalid_value").error!.issues
).toMatchInlineSnapshot(`
[
{
"code": "invalid_format",
"format": "ksuid",
"message": "Invalid KSUID",
"origin": "string",
"path": [],
"pattern": "/^[A-Za-z0-9]{27}$/",
},
{
"code": "custom",
"message": "Invalid input",
"path": [],
},
]
`);
});

View File

@@ -0,0 +1,127 @@
import * as BufferLayout from '@solana/buffer-layout';
import {Signer} from '../keypair';
import assert from '../utils/assert';
import {VersionedMessage} from '../message/versioned';
import {SIGNATURE_LENGTH_IN_BYTES} from './constants';
import * as shortvec from '../utils/shortvec-encoding';
import * as Layout from '../layout';
import {sign} from '../utils/ed25519';
import {PublicKey} from '../publickey';
import {guardedSplice} from '../utils/guarded-array-utils';
export type TransactionVersion = 'legacy' | 0;
/**
* Versioned transaction class
*/
export class VersionedTransaction {
signatures: Array<Uint8Array>;
message: VersionedMessage;
get version(): TransactionVersion {
return this.message.version;
}
constructor(message: VersionedMessage, signatures?: Array<Uint8Array>) {
if (signatures !== undefined) {
assert(
signatures.length === message.header.numRequiredSignatures,
'Expected signatures length to be equal to the number of required signatures',
);
this.signatures = signatures;
} else {
const defaultSignatures = [];
for (let i = 0; i < message.header.numRequiredSignatures; i++) {
defaultSignatures.push(new Uint8Array(SIGNATURE_LENGTH_IN_BYTES));
}
this.signatures = defaultSignatures;
}
this.message = message;
}
serialize(): Uint8Array {
const serializedMessage = this.message.serialize();
const encodedSignaturesLength = Array<number>();
shortvec.encodeLength(encodedSignaturesLength, this.signatures.length);
const transactionLayout = BufferLayout.struct<{
encodedSignaturesLength: Uint8Array;
signatures: Array<Uint8Array>;
serializedMessage: Uint8Array;
}>([
BufferLayout.blob(
encodedSignaturesLength.length,
'encodedSignaturesLength',
),
BufferLayout.seq(
Layout.signature(),
this.signatures.length,
'signatures',
),
BufferLayout.blob(serializedMessage.length, 'serializedMessage'),
]);
const serializedTransaction = new Uint8Array(2048);
const serializedTransactionLength = transactionLayout.encode(
{
encodedSignaturesLength: new Uint8Array(encodedSignaturesLength),
signatures: this.signatures,
serializedMessage,
},
serializedTransaction,
);
return serializedTransaction.slice(0, serializedTransactionLength);
}
static deserialize(serializedTransaction: Uint8Array): VersionedTransaction {
let byteArray = [...serializedTransaction];
const signatures = [];
const signaturesLength = shortvec.decodeLength(byteArray);
for (let i = 0; i < signaturesLength; i++) {
signatures.push(
new Uint8Array(guardedSplice(byteArray, 0, SIGNATURE_LENGTH_IN_BYTES)),
);
}
const message = VersionedMessage.deserialize(new Uint8Array(byteArray));
return new VersionedTransaction(message, signatures);
}
sign(signers: Array<Signer>) {
const messageData = this.message.serialize();
const signerPubkeys = this.message.staticAccountKeys.slice(
0,
this.message.header.numRequiredSignatures,
);
for (const signer of signers) {
const signerIndex = signerPubkeys.findIndex(pubkey =>
pubkey.equals(signer.publicKey),
);
assert(
signerIndex >= 0,
`Cannot sign with non signer key ${signer.publicKey.toBase58()}`,
);
this.signatures[signerIndex] = sign(messageData, signer.secretKey);
}
}
addSignature(publicKey: PublicKey, signature: Uint8Array) {
assert(signature.byteLength === 64, 'Signature must be 64 bytes long');
const signerPubkeys = this.message.staticAccountKeys.slice(
0,
this.message.header.numRequiredSignatures,
);
const signerIndex = signerPubkeys.findIndex(pubkey =>
pubkey.equals(publicKey),
);
assert(
signerIndex >= 0,
`Can not add signature; \`${publicKey.toBase58()}\` is not required to sign this transaction`,
);
this.signatures[signerIndex] = signature;
}
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"coercions.d.ts","sourceRoot":"","sources":["../../src/structs/coercions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAM,OAAO,EAAE,MAAM,cAAc,CAAA;AAIlD;;;;;;;;;GASG;AAEH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC5B,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EACpB,SAAS,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,EACzB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CASd;AAED;;;;;GAKG;AAEH,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAC5B,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EACpB,QAAQ,EAAE,GAAG,EACb,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,OAAO,CAAA;CACZ,GACL,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CA0Bd;AAED;;;;;GAKG;AAEH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAEhE"}

View File

@@ -0,0 +1,20 @@
'use strict';
const {Transform} = require('stream');
const {next} = require('./asFun');
const {sanitize} = require('../index');
const comp = (...fns) => {
fns = fns.filter(fn => fn);
return fns.length
? new Transform({
writableObjectMode: true,
readableObjectMode: true,
transform(chunk, encoding, callback) {
next(chunk, fns, 0, value => sanitize(value, this)).then(() => callback(null), error => callback(error));
}
})
: null;
};
module.exports = comp;

View File

@@ -0,0 +1,7 @@
import type { StringReader, StringWriter } from './strings.cts';
export declare const comma: number;
export declare const semicolon: number;
export declare function decodeInteger(reader: StringReader, relative: number): number;
export declare function encodeInteger(builder: StringWriter, num: number, relative: number): number;
export declare function hasMoreVlq(reader: StringReader, max: number): boolean;
//# sourceMappingURL=vlq.d.ts.map