WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,397 @@
|
||||
const test = require('tap').test
|
||||
const fss = require('./')
|
||||
const clone = require('clone')
|
||||
const s = JSON.stringify
|
||||
const stream = require('stream')
|
||||
|
||||
test('circular reference to root', function (assert) {
|
||||
const fixture = { name: 'Tywin Lannister' }
|
||||
fixture.circle = fixture
|
||||
const expected = s({ name: 'Tywin Lannister', circle: '[Circular]' })
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('circular getter reference to root', function (assert) {
|
||||
const fixture = {
|
||||
name: 'Tywin Lannister',
|
||||
get circle () {
|
||||
return fixture
|
||||
}
|
||||
}
|
||||
const expected = s({ name: 'Tywin Lannister', circle: '[Circular]' })
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('nested circular reference to root', function (assert) {
|
||||
const fixture = { name: 'Tywin Lannister' }
|
||||
fixture.id = { circle: fixture }
|
||||
const expected = s({ name: 'Tywin Lannister', id: { circle: '[Circular]' } })
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('child circular reference', function (assert) {
|
||||
const fixture = {
|
||||
name: 'Tywin Lannister',
|
||||
child: { name: 'Tyrion Lannister' }
|
||||
}
|
||||
fixture.child.dinklage = fixture.child
|
||||
const expected = s({
|
||||
name: 'Tywin Lannister',
|
||||
child: {
|
||||
name: 'Tyrion Lannister',
|
||||
dinklage: '[Circular]'
|
||||
}
|
||||
})
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('nested child circular reference', function (assert) {
|
||||
const fixture = {
|
||||
name: 'Tywin Lannister',
|
||||
child: { name: 'Tyrion Lannister' }
|
||||
}
|
||||
fixture.child.actor = { dinklage: fixture.child }
|
||||
const expected = s({
|
||||
name: 'Tywin Lannister',
|
||||
child: {
|
||||
name: 'Tyrion Lannister',
|
||||
actor: { dinklage: '[Circular]' }
|
||||
}
|
||||
})
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('circular objects in an array', function (assert) {
|
||||
const fixture = { name: 'Tywin Lannister' }
|
||||
fixture.hand = [fixture, fixture]
|
||||
const expected = s({
|
||||
name: 'Tywin Lannister',
|
||||
hand: ['[Circular]', '[Circular]']
|
||||
})
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('nested circular references in an array', function (assert) {
|
||||
const fixture = {
|
||||
name: 'Tywin Lannister',
|
||||
offspring: [{ name: 'Tyrion Lannister' }, { name: 'Cersei Lannister' }]
|
||||
}
|
||||
fixture.offspring[0].dinklage = fixture.offspring[0]
|
||||
fixture.offspring[1].headey = fixture.offspring[1]
|
||||
|
||||
const expected = s({
|
||||
name: 'Tywin Lannister',
|
||||
offspring: [
|
||||
{ name: 'Tyrion Lannister', dinklage: '[Circular]' },
|
||||
{ name: 'Cersei Lannister', headey: '[Circular]' }
|
||||
]
|
||||
})
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('circular arrays', function (assert) {
|
||||
const fixture = []
|
||||
fixture.push(fixture, fixture)
|
||||
const expected = s(['[Circular]', '[Circular]'])
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('nested circular arrays', function (assert) {
|
||||
const fixture = []
|
||||
fixture.push(
|
||||
{ name: 'Jon Snow', bastards: fixture },
|
||||
{ name: 'Ramsay Bolton', bastards: fixture }
|
||||
)
|
||||
const expected = s([
|
||||
{ name: 'Jon Snow', bastards: '[Circular]' },
|
||||
{ name: 'Ramsay Bolton', bastards: '[Circular]' }
|
||||
])
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('repeated non-circular references in objects', function (assert) {
|
||||
const daenerys = { name: 'Daenerys Targaryen' }
|
||||
const fixture = {
|
||||
motherOfDragons: daenerys,
|
||||
queenOfMeereen: daenerys
|
||||
}
|
||||
const expected = s(fixture)
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('repeated non-circular references in arrays', function (assert) {
|
||||
const daenerys = { name: 'Daenerys Targaryen' }
|
||||
const fixture = [daenerys, daenerys]
|
||||
const expected = s(fixture)
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('double child circular reference', function (assert) {
|
||||
// create circular reference
|
||||
const child = { name: 'Tyrion Lannister' }
|
||||
child.dinklage = child
|
||||
|
||||
// include it twice in the fixture
|
||||
const fixture = { name: 'Tywin Lannister', childA: child, childB: child }
|
||||
const cloned = clone(fixture)
|
||||
const expected = s({
|
||||
name: 'Tywin Lannister',
|
||||
childA: {
|
||||
name: 'Tyrion Lannister',
|
||||
dinklage: '[Circular]'
|
||||
},
|
||||
childB: {
|
||||
name: 'Tyrion Lannister',
|
||||
dinklage: '[Circular]'
|
||||
}
|
||||
})
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
|
||||
// check if the fixture has not been modified
|
||||
assert.same(fixture, cloned)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('child circular reference with toJSON', function (assert) {
|
||||
// Create a test object that has an overridden `toJSON` property
|
||||
TestObject.prototype.toJSON = function () {
|
||||
return { special: 'case' }
|
||||
}
|
||||
function TestObject (content) {}
|
||||
|
||||
// Creating a simple circular object structure
|
||||
const parentObject = {}
|
||||
parentObject.childObject = new TestObject()
|
||||
parentObject.childObject.parentObject = parentObject
|
||||
|
||||
// Creating a simple circular object structure
|
||||
const otherParentObject = new TestObject()
|
||||
otherParentObject.otherChildObject = {}
|
||||
otherParentObject.otherChildObject.otherParentObject = otherParentObject
|
||||
|
||||
// Making sure our original tests work
|
||||
assert.same(parentObject.childObject.parentObject, parentObject)
|
||||
assert.same(
|
||||
otherParentObject.otherChildObject.otherParentObject,
|
||||
otherParentObject
|
||||
)
|
||||
|
||||
// Should both be idempotent
|
||||
assert.equal(fss(parentObject), '{"childObject":{"special":"case"}}')
|
||||
assert.equal(fss(otherParentObject), '{"special":"case"}')
|
||||
|
||||
// Therefore the following assertion should be `true`
|
||||
assert.same(parentObject.childObject.parentObject, parentObject)
|
||||
assert.same(
|
||||
otherParentObject.otherChildObject.otherParentObject,
|
||||
otherParentObject
|
||||
)
|
||||
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('null object', function (assert) {
|
||||
const expected = s(null)
|
||||
const actual = fss(null)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('null property', function (assert) {
|
||||
const expected = s({ f: null })
|
||||
const actual = fss({ f: null })
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('nested child circular reference in toJSON', function (assert) {
|
||||
const circle = { some: 'data' }
|
||||
circle.circle = circle
|
||||
const a = {
|
||||
b: {
|
||||
toJSON: function () {
|
||||
a.b = 2
|
||||
return '[Redacted]'
|
||||
}
|
||||
},
|
||||
baz: {
|
||||
circle,
|
||||
toJSON: function () {
|
||||
a.baz = circle
|
||||
return '[Redacted]'
|
||||
}
|
||||
}
|
||||
}
|
||||
const o = {
|
||||
a,
|
||||
bar: a
|
||||
}
|
||||
|
||||
const expected = s({
|
||||
a: {
|
||||
b: '[Redacted]',
|
||||
baz: '[Redacted]'
|
||||
},
|
||||
bar: {
|
||||
b: 2,
|
||||
baz: {
|
||||
some: 'data',
|
||||
circle: '[Circular]'
|
||||
}
|
||||
}
|
||||
})
|
||||
const actual = fss(o)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('circular getters are restored when stringified', function (assert) {
|
||||
const fixture = {
|
||||
name: 'Tywin Lannister',
|
||||
get circle () {
|
||||
return fixture
|
||||
}
|
||||
}
|
||||
fss(fixture)
|
||||
|
||||
assert.equal(fixture.circle, fixture)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('non-configurable circular getters use a replacer instead of markers', function (assert) {
|
||||
const fixture = { name: 'Tywin Lannister' }
|
||||
Object.defineProperty(fixture, 'circle', {
|
||||
configurable: false,
|
||||
get: function () {
|
||||
return fixture
|
||||
},
|
||||
enumerable: true
|
||||
})
|
||||
|
||||
fss(fixture)
|
||||
|
||||
assert.equal(fixture.circle, fixture)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('getter child circular reference are replaced instead of marked', function (assert) {
|
||||
const fixture = {
|
||||
name: 'Tywin Lannister',
|
||||
child: {
|
||||
name: 'Tyrion Lannister',
|
||||
get dinklage () {
|
||||
return fixture.child
|
||||
}
|
||||
},
|
||||
get self () {
|
||||
return fixture
|
||||
}
|
||||
}
|
||||
|
||||
const expected = s({
|
||||
name: 'Tywin Lannister',
|
||||
child: {
|
||||
name: 'Tyrion Lannister',
|
||||
dinklage: '[Circular]'
|
||||
},
|
||||
self: '[Circular]'
|
||||
})
|
||||
const actual = fss(fixture)
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('Proxy throwing', function (assert) {
|
||||
assert.plan(1)
|
||||
const s = new stream.PassThrough()
|
||||
s.resume()
|
||||
s.write('', () => {
|
||||
assert.end()
|
||||
})
|
||||
const actual = fss({ s, p: new Proxy({}, { get () { throw new Error('kaboom') } }) })
|
||||
assert.equal(actual, '"[unable to serialize, circular reference is too complex to analyze]"')
|
||||
})
|
||||
|
||||
test('depthLimit option - will replace deep objects', function (assert) {
|
||||
const fixture = {
|
||||
name: 'Tywin Lannister',
|
||||
child: {
|
||||
name: 'Tyrion Lannister'
|
||||
},
|
||||
get self () {
|
||||
return fixture
|
||||
}
|
||||
}
|
||||
|
||||
const expected = s({
|
||||
name: 'Tywin Lannister',
|
||||
child: '[...]',
|
||||
self: '[Circular]'
|
||||
})
|
||||
const actual = fss(fixture, undefined, undefined, {
|
||||
depthLimit: 1,
|
||||
edgesLimit: 1
|
||||
})
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
|
||||
test('edgesLimit option - will replace deep objects', function (assert) {
|
||||
const fixture = {
|
||||
object: {
|
||||
1: { test: 'test' },
|
||||
2: { test: 'test' },
|
||||
3: { test: 'test' },
|
||||
4: { test: 'test' }
|
||||
},
|
||||
array: [
|
||||
{ test: 'test' },
|
||||
{ test: 'test' },
|
||||
{ test: 'test' },
|
||||
{ test: 'test' }
|
||||
],
|
||||
get self () {
|
||||
return fixture
|
||||
}
|
||||
}
|
||||
|
||||
const expected = s({
|
||||
object: {
|
||||
1: { test: 'test' },
|
||||
2: { test: 'test' },
|
||||
3: { test: 'test' },
|
||||
4: '[...]'
|
||||
},
|
||||
array: [{ test: 'test' }, { test: 'test' }, { test: 'test' }, '[...]'],
|
||||
self: '[Circular]'
|
||||
})
|
||||
const actual = fss(fixture, undefined, undefined, {
|
||||
depthLimit: 3,
|
||||
edgesLimit: 3
|
||||
})
|
||||
assert.equal(actual, expected)
|
||||
assert.end()
|
||||
})
|
||||
@@ -0,0 +1,594 @@
|
||||
/* -*- Mode: js; js-indent-level: 2; -*- */
|
||||
/*
|
||||
* Copyright 2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a helper function for getting values from parameter/options
|
||||
* objects.
|
||||
*
|
||||
* @param args The object we are extracting values from
|
||||
* @param name The name of the property we are getting.
|
||||
* @param defaultValue An optional value to return if the property is missing
|
||||
* from the object. If this is not specified and the property is missing, an
|
||||
* error will be thrown.
|
||||
*/
|
||||
function getArg(aArgs, aName, aDefaultValue) {
|
||||
if (aName in aArgs) {
|
||||
return aArgs[aName];
|
||||
} else if (arguments.length === 3) {
|
||||
return aDefaultValue;
|
||||
} else {
|
||||
throw new Error('"' + aName + '" is a required argument.');
|
||||
}
|
||||
}
|
||||
exports.getArg = getArg;
|
||||
|
||||
var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;
|
||||
var dataUrlRegexp = /^data:.+\,.+$/;
|
||||
|
||||
function urlParse(aUrl) {
|
||||
var match = aUrl.match(urlRegexp);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
scheme: match[1],
|
||||
auth: match[2],
|
||||
host: match[3],
|
||||
port: match[4],
|
||||
path: match[5]
|
||||
};
|
||||
}
|
||||
exports.urlParse = urlParse;
|
||||
|
||||
function urlGenerate(aParsedUrl) {
|
||||
var url = '';
|
||||
if (aParsedUrl.scheme) {
|
||||
url += aParsedUrl.scheme + ':';
|
||||
}
|
||||
url += '//';
|
||||
if (aParsedUrl.auth) {
|
||||
url += aParsedUrl.auth + '@';
|
||||
}
|
||||
if (aParsedUrl.host) {
|
||||
url += aParsedUrl.host;
|
||||
}
|
||||
if (aParsedUrl.port) {
|
||||
url += ":" + aParsedUrl.port
|
||||
}
|
||||
if (aParsedUrl.path) {
|
||||
url += aParsedUrl.path;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
exports.urlGenerate = urlGenerate;
|
||||
|
||||
var MAX_CACHED_INPUTS = 32;
|
||||
|
||||
/**
|
||||
* Takes some function `f(input) -> result` and returns a memoized version of
|
||||
* `f`.
|
||||
*
|
||||
* We keep at most `MAX_CACHED_INPUTS` memoized results of `f` alive. The
|
||||
* memoization is a dumb-simple, linear least-recently-used cache.
|
||||
*/
|
||||
function lruMemoize(f) {
|
||||
var cache = [];
|
||||
|
||||
return function(input) {
|
||||
for (var i = 0; i < cache.length; i++) {
|
||||
if (cache[i].input === input) {
|
||||
var temp = cache[0];
|
||||
cache[0] = cache[i];
|
||||
cache[i] = temp;
|
||||
return cache[0].result;
|
||||
}
|
||||
}
|
||||
|
||||
var result = f(input);
|
||||
|
||||
cache.unshift({
|
||||
input,
|
||||
result,
|
||||
});
|
||||
|
||||
if (cache.length > MAX_CACHED_INPUTS) {
|
||||
cache.pop();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a path, or the path portion of a URL:
|
||||
*
|
||||
* - Replaces consecutive slashes with one slash.
|
||||
* - Removes unnecessary '.' parts.
|
||||
* - Removes unnecessary '<dir>/..' parts.
|
||||
*
|
||||
* Based on code in the Node.js 'path' core module.
|
||||
*
|
||||
* @param aPath The path or url to normalize.
|
||||
*/
|
||||
var normalize = lruMemoize(function normalize(aPath) {
|
||||
var path = aPath;
|
||||
var url = urlParse(aPath);
|
||||
if (url) {
|
||||
if (!url.path) {
|
||||
return aPath;
|
||||
}
|
||||
path = url.path;
|
||||
}
|
||||
var isAbsolute = exports.isAbsolute(path);
|
||||
// Split the path into parts between `/` characters. This is much faster than
|
||||
// using `.split(/\/+/g)`.
|
||||
var parts = [];
|
||||
var start = 0;
|
||||
var i = 0;
|
||||
while (true) {
|
||||
start = i;
|
||||
i = path.indexOf("/", start);
|
||||
if (i === -1) {
|
||||
parts.push(path.slice(start));
|
||||
break;
|
||||
} else {
|
||||
parts.push(path.slice(start, i));
|
||||
while (i < path.length && path[i] === "/") {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
|
||||
part = parts[i];
|
||||
if (part === '.') {
|
||||
parts.splice(i, 1);
|
||||
} else if (part === '..') {
|
||||
up++;
|
||||
} else if (up > 0) {
|
||||
if (part === '') {
|
||||
// The first part is blank if the path is absolute. Trying to go
|
||||
// above the root is a no-op. Therefore we can remove all '..' parts
|
||||
// directly after the root.
|
||||
parts.splice(i + 1, up);
|
||||
up = 0;
|
||||
} else {
|
||||
parts.splice(i, 2);
|
||||
up--;
|
||||
}
|
||||
}
|
||||
}
|
||||
path = parts.join('/');
|
||||
|
||||
if (path === '') {
|
||||
path = isAbsolute ? '/' : '.';
|
||||
}
|
||||
|
||||
if (url) {
|
||||
url.path = path;
|
||||
return urlGenerate(url);
|
||||
}
|
||||
return path;
|
||||
});
|
||||
exports.normalize = normalize;
|
||||
|
||||
/**
|
||||
* Joins two paths/URLs.
|
||||
*
|
||||
* @param aRoot The root path or URL.
|
||||
* @param aPath The path or URL to be joined with the root.
|
||||
*
|
||||
* - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
|
||||
* scheme-relative URL: Then the scheme of aRoot, if any, is prepended
|
||||
* first.
|
||||
* - Otherwise aPath is a path. If aRoot is a URL, then its path portion
|
||||
* is updated with the result and aRoot is returned. Otherwise the result
|
||||
* is returned.
|
||||
* - If aPath is absolute, the result is aPath.
|
||||
* - Otherwise the two paths are joined with a slash.
|
||||
* - Joining for example 'http://' and 'www.example.com' is also supported.
|
||||
*/
|
||||
function join(aRoot, aPath) {
|
||||
if (aRoot === "") {
|
||||
aRoot = ".";
|
||||
}
|
||||
if (aPath === "") {
|
||||
aPath = ".";
|
||||
}
|
||||
var aPathUrl = urlParse(aPath);
|
||||
var aRootUrl = urlParse(aRoot);
|
||||
if (aRootUrl) {
|
||||
aRoot = aRootUrl.path || '/';
|
||||
}
|
||||
|
||||
// `join(foo, '//www.example.org')`
|
||||
if (aPathUrl && !aPathUrl.scheme) {
|
||||
if (aRootUrl) {
|
||||
aPathUrl.scheme = aRootUrl.scheme;
|
||||
}
|
||||
return urlGenerate(aPathUrl);
|
||||
}
|
||||
|
||||
if (aPathUrl || aPath.match(dataUrlRegexp)) {
|
||||
return aPath;
|
||||
}
|
||||
|
||||
// `join('http://', 'www.example.com')`
|
||||
if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
|
||||
aRootUrl.host = aPath;
|
||||
return urlGenerate(aRootUrl);
|
||||
}
|
||||
|
||||
var joined = aPath.charAt(0) === '/'
|
||||
? aPath
|
||||
: normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
|
||||
|
||||
if (aRootUrl) {
|
||||
aRootUrl.path = joined;
|
||||
return urlGenerate(aRootUrl);
|
||||
}
|
||||
return joined;
|
||||
}
|
||||
exports.join = join;
|
||||
|
||||
exports.isAbsolute = function (aPath) {
|
||||
return aPath.charAt(0) === '/' || urlRegexp.test(aPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a path relative to a URL or another path.
|
||||
*
|
||||
* @param aRoot The root path or URL.
|
||||
* @param aPath The path or URL to be made relative to aRoot.
|
||||
*/
|
||||
function relative(aRoot, aPath) {
|
||||
if (aRoot === "") {
|
||||
aRoot = ".";
|
||||
}
|
||||
|
||||
aRoot = aRoot.replace(/\/$/, '');
|
||||
|
||||
// It is possible for the path to be above the root. In this case, simply
|
||||
// checking whether the root is a prefix of the path won't work. Instead, we
|
||||
// need to remove components from the root one by one, until either we find
|
||||
// a prefix that fits, or we run out of components to remove.
|
||||
var level = 0;
|
||||
while (aPath.indexOf(aRoot + '/') !== 0) {
|
||||
var index = aRoot.lastIndexOf("/");
|
||||
if (index < 0) {
|
||||
return aPath;
|
||||
}
|
||||
|
||||
// If the only part of the root that is left is the scheme (i.e. http://,
|
||||
// file:///, etc.), one or more slashes (/), or simply nothing at all, we
|
||||
// have exhausted all components, so the path is not relative to the root.
|
||||
aRoot = aRoot.slice(0, index);
|
||||
if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
|
||||
return aPath;
|
||||
}
|
||||
|
||||
++level;
|
||||
}
|
||||
|
||||
// Make sure we add a "../" for each component we removed from the root.
|
||||
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
|
||||
}
|
||||
exports.relative = relative;
|
||||
|
||||
var supportsNullProto = (function () {
|
||||
var obj = Object.create(null);
|
||||
return !('__proto__' in obj);
|
||||
}());
|
||||
|
||||
function identity (s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Because behavior goes wacky when you set `__proto__` on objects, we
|
||||
* have to prefix all the strings in our set with an arbitrary character.
|
||||
*
|
||||
* See https://github.com/mozilla/source-map/pull/31 and
|
||||
* https://github.com/mozilla/source-map/issues/30
|
||||
*
|
||||
* @param String aStr
|
||||
*/
|
||||
function toSetString(aStr) {
|
||||
if (isProtoString(aStr)) {
|
||||
return '$' + aStr;
|
||||
}
|
||||
|
||||
return aStr;
|
||||
}
|
||||
exports.toSetString = supportsNullProto ? identity : toSetString;
|
||||
|
||||
function fromSetString(aStr) {
|
||||
if (isProtoString(aStr)) {
|
||||
return aStr.slice(1);
|
||||
}
|
||||
|
||||
return aStr;
|
||||
}
|
||||
exports.fromSetString = supportsNullProto ? identity : fromSetString;
|
||||
|
||||
function isProtoString(s) {
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var length = s.length;
|
||||
|
||||
if (length < 9 /* "__proto__".length */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s.charCodeAt(length - 1) !== 95 /* '_' */ ||
|
||||
s.charCodeAt(length - 2) !== 95 /* '_' */ ||
|
||||
s.charCodeAt(length - 3) !== 111 /* 'o' */ ||
|
||||
s.charCodeAt(length - 4) !== 116 /* 't' */ ||
|
||||
s.charCodeAt(length - 5) !== 111 /* 'o' */ ||
|
||||
s.charCodeAt(length - 6) !== 114 /* 'r' */ ||
|
||||
s.charCodeAt(length - 7) !== 112 /* 'p' */ ||
|
||||
s.charCodeAt(length - 8) !== 95 /* '_' */ ||
|
||||
s.charCodeAt(length - 9) !== 95 /* '_' */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = length - 10; i >= 0; i--) {
|
||||
if (s.charCodeAt(i) !== 36 /* '$' */) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator between two mappings where the original positions are compared.
|
||||
*
|
||||
* Optionally pass in `true` as `onlyCompareGenerated` to consider two
|
||||
* mappings with the same original source/line/column, but different generated
|
||||
* line and column the same. Useful when searching for a mapping with a
|
||||
* stubbed out mapping.
|
||||
*/
|
||||
function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
|
||||
var cmp = strcmp(mappingA.source, mappingB.source);
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalLine - mappingB.originalLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalColumn - mappingB.originalColumn;
|
||||
if (cmp !== 0 || onlyCompareOriginal) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.generatedLine - mappingB.generatedLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
return strcmp(mappingA.name, mappingB.name);
|
||||
}
|
||||
exports.compareByOriginalPositions = compareByOriginalPositions;
|
||||
|
||||
function compareByOriginalPositionsNoSource(mappingA, mappingB, onlyCompareOriginal) {
|
||||
var cmp
|
||||
|
||||
cmp = mappingA.originalLine - mappingB.originalLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalColumn - mappingB.originalColumn;
|
||||
if (cmp !== 0 || onlyCompareOriginal) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.generatedLine - mappingB.generatedLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
return strcmp(mappingA.name, mappingB.name);
|
||||
}
|
||||
exports.compareByOriginalPositionsNoSource = compareByOriginalPositionsNoSource;
|
||||
|
||||
/**
|
||||
* Comparator between two mappings with deflated source and name indices where
|
||||
* the generated positions are compared.
|
||||
*
|
||||
* Optionally pass in `true` as `onlyCompareGenerated` to consider two
|
||||
* mappings with the same generated line and column, but different
|
||||
* source/name/original line and column the same. Useful when searching for a
|
||||
* mapping with a stubbed out mapping.
|
||||
*/
|
||||
function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
|
||||
var cmp = mappingA.generatedLine - mappingB.generatedLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
|
||||
if (cmp !== 0 || onlyCompareGenerated) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = strcmp(mappingA.source, mappingB.source);
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalLine - mappingB.originalLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalColumn - mappingB.originalColumn;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
return strcmp(mappingA.name, mappingB.name);
|
||||
}
|
||||
exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
|
||||
|
||||
function compareByGeneratedPositionsDeflatedNoLine(mappingA, mappingB, onlyCompareGenerated) {
|
||||
var cmp = mappingA.generatedColumn - mappingB.generatedColumn;
|
||||
if (cmp !== 0 || onlyCompareGenerated) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = strcmp(mappingA.source, mappingB.source);
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalLine - mappingB.originalLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalColumn - mappingB.originalColumn;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
return strcmp(mappingA.name, mappingB.name);
|
||||
}
|
||||
exports.compareByGeneratedPositionsDeflatedNoLine = compareByGeneratedPositionsDeflatedNoLine;
|
||||
|
||||
function strcmp(aStr1, aStr2) {
|
||||
if (aStr1 === aStr2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (aStr1 === null) {
|
||||
return 1; // aStr2 !== null
|
||||
}
|
||||
|
||||
if (aStr2 === null) {
|
||||
return -1; // aStr1 !== null
|
||||
}
|
||||
|
||||
if (aStr1 > aStr2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator between two mappings with inflated source and name strings where
|
||||
* the generated positions are compared.
|
||||
*/
|
||||
function compareByGeneratedPositionsInflated(mappingA, mappingB) {
|
||||
var cmp = mappingA.generatedLine - mappingB.generatedLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = strcmp(mappingA.source, mappingB.source);
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalLine - mappingB.originalLine;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = mappingA.originalColumn - mappingB.originalColumn;
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
return strcmp(mappingA.name, mappingB.name);
|
||||
}
|
||||
exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
|
||||
|
||||
/**
|
||||
* Strip any JSON XSSI avoidance prefix from the string (as documented
|
||||
* in the source maps specification), and then parse the string as
|
||||
* JSON.
|
||||
*/
|
||||
function parseSourceMapInput(str) {
|
||||
return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, ''));
|
||||
}
|
||||
exports.parseSourceMapInput = parseSourceMapInput;
|
||||
|
||||
/**
|
||||
* Compute the URL of a source given the the source root, the source's
|
||||
* URL, and the source map's URL.
|
||||
*/
|
||||
function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) {
|
||||
sourceURL = sourceURL || '';
|
||||
|
||||
if (sourceRoot) {
|
||||
// This follows what Chrome does.
|
||||
if (sourceRoot[sourceRoot.length - 1] !== '/' && sourceURL[0] !== '/') {
|
||||
sourceRoot += '/';
|
||||
}
|
||||
// The spec says:
|
||||
// Line 4: An optional source root, useful for relocating source
|
||||
// files on a server or removing repeated values in the
|
||||
// “sources” entry. This value is prepended to the individual
|
||||
// entries in the “source” field.
|
||||
sourceURL = sourceRoot + sourceURL;
|
||||
}
|
||||
|
||||
// Historically, SourceMapConsumer did not take the sourceMapURL as
|
||||
// a parameter. This mode is still somewhat supported, which is why
|
||||
// this code block is conditional. However, it's preferable to pass
|
||||
// the source map URL to SourceMapConsumer, so that this function
|
||||
// can implement the source URL resolution algorithm as outlined in
|
||||
// the spec. This block is basically the equivalent of:
|
||||
// new URL(sourceURL, sourceMapURL).toString()
|
||||
// ... except it avoids using URL, which wasn't available in the
|
||||
// older releases of node still supported by this library.
|
||||
//
|
||||
// The spec says:
|
||||
// If the sources are not absolute URLs after prepending of the
|
||||
// “sourceRoot”, the sources are resolved relative to the
|
||||
// SourceMap (like resolving script src in a html document).
|
||||
if (sourceMapURL) {
|
||||
var parsed = urlParse(sourceMapURL);
|
||||
if (!parsed) {
|
||||
throw new Error("sourceMapURL could not be parsed");
|
||||
}
|
||||
if (parsed.path) {
|
||||
// Strip the last path component, but keep the "/".
|
||||
var index = parsed.path.lastIndexOf('/');
|
||||
if (index >= 0) {
|
||||
parsed.path = parsed.path.substring(0, index + 1);
|
||||
}
|
||||
}
|
||||
sourceURL = join(urlGenerate(parsed), sourceURL);
|
||||
}
|
||||
|
||||
return normalize(sourceURL);
|
||||
}
|
||||
exports.computeSourceURL = computeSourceURL;
|
||||
@@ -0,0 +1,52 @@
|
||||
# json-stringify-safe
|
||||
|
||||
Like JSON.stringify, but doesn't throw on circular references.
|
||||
|
||||
## Usage
|
||||
|
||||
Takes the same arguments as `JSON.stringify`.
|
||||
|
||||
```javascript
|
||||
var stringify = require('json-stringify-safe');
|
||||
var circularObj = {};
|
||||
circularObj.circularRef = circularObj;
|
||||
circularObj.list = [ circularObj, circularObj ];
|
||||
console.log(stringify(circularObj, null, 2));
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
{
|
||||
"circularRef": "[Circular]",
|
||||
"list": [
|
||||
"[Circular]",
|
||||
"[Circular]"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Details
|
||||
|
||||
```
|
||||
stringify(obj, serializer, indent, decycler)
|
||||
```
|
||||
|
||||
The first three arguments are the same as to JSON.stringify. The last
|
||||
is an argument that's only used when the object has been seen already.
|
||||
|
||||
The default `decycler` function returns the string `'[Circular]'`.
|
||||
If, for example, you pass in `function(k,v){}` (return nothing) then it
|
||||
will prune cycles. If you pass in `function(k,v){ return {foo: 'bar'}}`,
|
||||
then cyclical objects will always be represented as `{"foo":"bar"}` in
|
||||
the result.
|
||||
|
||||
```
|
||||
stringify.getSerialize(serializer, decycler)
|
||||
```
|
||||
|
||||
Returns a serializer that can be used elsewhere. This is the actual
|
||||
function that's passed to JSON.stringify.
|
||||
|
||||
**Note** that the function returned from `getSerialize` is stateful for now, so
|
||||
do **not** use it more than once.
|
||||
@@ -0,0 +1,445 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
import { EventEmitter } from "events";
|
||||
import {
|
||||
Agent,
|
||||
ClientRequest,
|
||||
ClientRequestArgs,
|
||||
IncomingMessage,
|
||||
OutgoingHttpHeaders,
|
||||
Server as HTTPServer,
|
||||
} from "http";
|
||||
import { Server as HTTPSServer } from "https";
|
||||
import { createConnection } from "net";
|
||||
import { Duplex, DuplexOptions } from "stream";
|
||||
import { SecureContextOptions } from "tls";
|
||||
import { URL } from "url";
|
||||
import { ZlibOptions } from "zlib";
|
||||
|
||||
// can not get all overload of BufferConstructor['from'], need to copy all it's first arguments here
|
||||
// https://github.com/microsoft/TypeScript/issues/32164
|
||||
type BufferLike =
|
||||
| string
|
||||
| Buffer
|
||||
| DataView
|
||||
| number
|
||||
| ArrayBufferView
|
||||
| Uint8Array
|
||||
| ArrayBuffer
|
||||
| SharedArrayBuffer
|
||||
| Blob
|
||||
| readonly any[]
|
||||
| readonly number[]
|
||||
| { valueOf(): ArrayBuffer }
|
||||
| { valueOf(): SharedArrayBuffer }
|
||||
| { valueOf(): Uint8Array }
|
||||
| { valueOf(): readonly number[] }
|
||||
| { valueOf(): string }
|
||||
| { [Symbol.toPrimitive](hint: string): string };
|
||||
|
||||
// WebSocket socket.
|
||||
declare class WebSocket extends EventEmitter {
|
||||
/** The connection is not yet open. */
|
||||
static readonly CONNECTING: 0;
|
||||
/** The connection is open and ready to communicate. */
|
||||
static readonly OPEN: 1;
|
||||
/** The connection is in the process of closing. */
|
||||
static readonly CLOSING: 2;
|
||||
/** The connection is closed. */
|
||||
static readonly CLOSED: 3;
|
||||
|
||||
binaryType: "nodebuffer" | "arraybuffer" | "fragments";
|
||||
readonly bufferedAmount: number;
|
||||
readonly extensions: string;
|
||||
/** Indicates whether the websocket is paused */
|
||||
readonly isPaused: boolean;
|
||||
readonly protocol: string;
|
||||
/** The current state of the connection */
|
||||
readonly readyState:
|
||||
| typeof WebSocket.CONNECTING
|
||||
| typeof WebSocket.OPEN
|
||||
| typeof WebSocket.CLOSING
|
||||
| typeof WebSocket.CLOSED;
|
||||
readonly url: string;
|
||||
|
||||
/** The connection is not yet open. */
|
||||
readonly CONNECTING: 0;
|
||||
/** The connection is open and ready to communicate. */
|
||||
readonly OPEN: 1;
|
||||
/** The connection is in the process of closing. */
|
||||
readonly CLOSING: 2;
|
||||
/** The connection is closed. */
|
||||
readonly CLOSED: 3;
|
||||
|
||||
onopen: ((event: WebSocket.Event) => void) | null;
|
||||
onerror: ((event: WebSocket.ErrorEvent) => void) | null;
|
||||
onclose: ((event: WebSocket.CloseEvent) => void) | null;
|
||||
onmessage: ((event: WebSocket.MessageEvent) => void) | null;
|
||||
|
||||
constructor(address: null);
|
||||
constructor(address: string | URL, options?: WebSocket.ClientOptions | ClientRequestArgs);
|
||||
constructor(
|
||||
address: string | URL,
|
||||
protocols?: string | string[],
|
||||
options?: WebSocket.ClientOptions | ClientRequestArgs,
|
||||
);
|
||||
|
||||
close(code?: number, data?: string | Buffer): void;
|
||||
ping(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
|
||||
pong(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
|
||||
// https://github.com/websockets/ws/issues/2076#issuecomment-1250354722
|
||||
send(data: BufferLike, cb?: (err?: Error) => void): void;
|
||||
send(
|
||||
data: BufferLike,
|
||||
options: {
|
||||
mask?: boolean | undefined;
|
||||
binary?: boolean | undefined;
|
||||
compress?: boolean | undefined;
|
||||
fin?: boolean | undefined;
|
||||
},
|
||||
cb?: (err?: Error) => void,
|
||||
): void;
|
||||
terminate(): void;
|
||||
|
||||
/**
|
||||
* Pause the websocket causing it to stop emitting events. Some events can still be
|
||||
* emitted after this is called, until all buffered data is consumed. This method
|
||||
* is a noop if the ready state is `CONNECTING` or `CLOSED`.
|
||||
*/
|
||||
pause(): void;
|
||||
/**
|
||||
* Make a paused socket resume emitting events. This method is a noop if the ready
|
||||
* state is `CONNECTING` or `CLOSED`.
|
||||
*/
|
||||
resume(): void;
|
||||
|
||||
// HTML5 WebSocket events
|
||||
addEventListener<K extends keyof WebSocket.WebSocketEventMap>(
|
||||
type: K,
|
||||
listener:
|
||||
| ((event: WebSocket.WebSocketEventMap[K]) => void)
|
||||
| { handleEvent(event: WebSocket.WebSocketEventMap[K]): void },
|
||||
options?: WebSocket.EventListenerOptions,
|
||||
): void;
|
||||
removeEventListener<K extends keyof WebSocket.WebSocketEventMap>(
|
||||
type: K,
|
||||
listener:
|
||||
| ((event: WebSocket.WebSocketEventMap[K]) => void)
|
||||
| { handleEvent(event: WebSocket.WebSocketEventMap[K]): void },
|
||||
): void;
|
||||
|
||||
// Events
|
||||
on(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||
on(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||
on(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||
on(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||
on(event: "open", listener: (this: WebSocket) => void): this;
|
||||
on(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||
on(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||
on(
|
||||
event: "unexpected-response",
|
||||
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||
): this;
|
||||
on(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||
|
||||
once(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||
once(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||
once(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||
once(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||
once(event: "open", listener: (this: WebSocket) => void): this;
|
||||
once(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||
once(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||
once(
|
||||
event: "unexpected-response",
|
||||
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||
): this;
|
||||
once(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||
|
||||
off(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||
off(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||
off(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||
off(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||
off(event: "open", listener: (this: WebSocket) => void): this;
|
||||
off(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||
off(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||
off(
|
||||
event: "unexpected-response",
|
||||
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||
): this;
|
||||
off(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||
|
||||
addListener(event: "close", listener: (code: number, reason: Buffer) => void): this;
|
||||
addListener(event: "error", listener: (error: Error) => void): this;
|
||||
addListener(event: "upgrade", listener: (request: IncomingMessage) => void): this;
|
||||
addListener(event: "message", listener: (data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||
addListener(event: "open", listener: () => void): this;
|
||||
addListener(event: "ping" | "pong", listener: (data: Buffer) => void): this;
|
||||
addListener(event: "redirect", listener: (url: string, request: ClientRequest) => void): this;
|
||||
addListener(
|
||||
event: "unexpected-response",
|
||||
listener: (request: ClientRequest, response: IncomingMessage) => void,
|
||||
): this;
|
||||
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
|
||||
removeListener(event: "close", listener: (code: number, reason: Buffer) => void): this;
|
||||
removeListener(event: "error", listener: (error: Error) => void): this;
|
||||
removeListener(event: "upgrade", listener: (request: IncomingMessage) => void): this;
|
||||
removeListener(event: "message", listener: (data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||
removeListener(event: "open", listener: () => void): this;
|
||||
removeListener(event: "ping" | "pong", listener: (data: Buffer) => void): this;
|
||||
removeListener(event: "redirect", listener: (url: string, request: ClientRequest) => void): this;
|
||||
removeListener(
|
||||
event: "unexpected-response",
|
||||
listener: (request: ClientRequest, response: IncomingMessage) => void,
|
||||
): this;
|
||||
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
}
|
||||
|
||||
declare const WebSocketAlias: typeof WebSocket;
|
||||
interface WebSocketAlias extends WebSocket {} // eslint-disable-line @typescript-eslint/no-empty-interface
|
||||
|
||||
declare namespace WebSocket {
|
||||
/**
|
||||
* Data represents the raw message payload received over the WebSocket.
|
||||
*/
|
||||
type RawData = Buffer | ArrayBuffer | Buffer[];
|
||||
|
||||
/**
|
||||
* Data represents the message payload received over the WebSocket.
|
||||
*/
|
||||
type Data = string | Buffer | ArrayBuffer | Buffer[];
|
||||
|
||||
/**
|
||||
* CertMeta represents the accepted types for certificate & key data.
|
||||
*/
|
||||
type CertMeta = string | string[] | Buffer | Buffer[];
|
||||
|
||||
/**
|
||||
* VerifyClientCallbackSync is a synchronous callback used to inspect the
|
||||
* incoming message. The return value (boolean) of the function determines
|
||||
* whether or not to accept the handshake.
|
||||
*/
|
||||
type VerifyClientCallbackSync<Request extends IncomingMessage = IncomingMessage> = (info: {
|
||||
origin: string;
|
||||
secure: boolean;
|
||||
req: Request;
|
||||
}) => boolean;
|
||||
|
||||
/**
|
||||
* VerifyClientCallbackAsync is an asynchronous callback used to inspect the
|
||||
* incoming message. The return value (boolean) of the function determines
|
||||
* whether or not to accept the handshake.
|
||||
*/
|
||||
type VerifyClientCallbackAsync<Request extends IncomingMessage = IncomingMessage> = (
|
||||
info: { origin: string; secure: boolean; req: Request },
|
||||
callback: (res: boolean, code?: number, message?: string, headers?: OutgoingHttpHeaders) => void,
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* FinishRequestCallback is a callback for last minute customization of the
|
||||
* headers. If finishRequest is set, then it has the responsibility to call
|
||||
* request.end() once it is done setting request headers.
|
||||
*/
|
||||
type FinishRequestCallback = (request: ClientRequest, websocket: WebSocket) => void;
|
||||
|
||||
interface ClientOptions extends SecureContextOptions {
|
||||
protocol?: string | undefined;
|
||||
followRedirects?: boolean | undefined;
|
||||
generateMask?(mask: Buffer): void;
|
||||
handshakeTimeout?: number | undefined;
|
||||
maxRedirects?: number | undefined;
|
||||
perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
|
||||
localAddress?: string | undefined;
|
||||
protocolVersion?: number | undefined;
|
||||
headers?: { [key: string]: string } | undefined;
|
||||
origin?: string | undefined;
|
||||
agent?: Agent | undefined;
|
||||
host?: string | undefined;
|
||||
family?: number | undefined;
|
||||
checkServerIdentity?(servername: string, cert: CertMeta): boolean;
|
||||
rejectUnauthorized?: boolean | undefined;
|
||||
allowSynchronousEvents?: boolean | undefined;
|
||||
autoPong?: boolean | undefined;
|
||||
maxPayload?: number | undefined;
|
||||
skipUTF8Validation?: boolean | undefined;
|
||||
createConnection?: typeof createConnection | undefined;
|
||||
finishRequest?: FinishRequestCallback | undefined;
|
||||
}
|
||||
|
||||
interface PerMessageDeflateOptions {
|
||||
serverNoContextTakeover?: boolean | undefined;
|
||||
clientNoContextTakeover?: boolean | undefined;
|
||||
serverMaxWindowBits?: number | undefined;
|
||||
clientMaxWindowBits?: number | undefined;
|
||||
zlibDeflateOptions?: {
|
||||
flush?: number | undefined;
|
||||
finishFlush?: number | undefined;
|
||||
chunkSize?: number | undefined;
|
||||
windowBits?: number | undefined;
|
||||
level?: number | undefined;
|
||||
memLevel?: number | undefined;
|
||||
strategy?: number | undefined;
|
||||
dictionary?: Buffer | Buffer[] | DataView | undefined;
|
||||
info?: boolean | undefined;
|
||||
} | undefined;
|
||||
zlibInflateOptions?: ZlibOptions | undefined;
|
||||
threshold?: number | undefined;
|
||||
concurrencyLimit?: number | undefined;
|
||||
}
|
||||
|
||||
interface Event {
|
||||
type: string;
|
||||
target: WebSocket;
|
||||
}
|
||||
|
||||
interface ErrorEvent {
|
||||
error: any;
|
||||
message: string;
|
||||
type: string;
|
||||
target: WebSocket;
|
||||
}
|
||||
|
||||
interface CloseEvent {
|
||||
wasClean: boolean;
|
||||
code: number;
|
||||
reason: string;
|
||||
type: string;
|
||||
target: WebSocket;
|
||||
}
|
||||
|
||||
interface MessageEvent {
|
||||
data: Data;
|
||||
type: string;
|
||||
target: WebSocket;
|
||||
}
|
||||
|
||||
interface WebSocketEventMap {
|
||||
open: Event;
|
||||
error: ErrorEvent;
|
||||
close: CloseEvent;
|
||||
message: MessageEvent;
|
||||
}
|
||||
|
||||
interface EventListenerOptions {
|
||||
once?: boolean | undefined;
|
||||
}
|
||||
|
||||
interface ServerOptions<
|
||||
U extends typeof WebSocket.WebSocket = typeof WebSocket.WebSocket,
|
||||
V extends typeof IncomingMessage = typeof IncomingMessage,
|
||||
> {
|
||||
host?: string | undefined;
|
||||
port?: number | undefined;
|
||||
backlog?: number | undefined;
|
||||
server?: HTTPServer<V> | HTTPSServer<V> | undefined;
|
||||
verifyClient?:
|
||||
| VerifyClientCallbackAsync<InstanceType<V>>
|
||||
| VerifyClientCallbackSync<InstanceType<V>>
|
||||
| undefined;
|
||||
handleProtocols?: (protocols: Set<string>, request: InstanceType<V>) => string | false;
|
||||
path?: string | undefined;
|
||||
noServer?: boolean | undefined;
|
||||
allowSynchronousEvents?: boolean | undefined;
|
||||
autoPong?: boolean | undefined;
|
||||
clientTracking?: boolean | undefined;
|
||||
perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
|
||||
maxPayload?: number | undefined;
|
||||
skipUTF8Validation?: boolean | undefined;
|
||||
WebSocket?: U | undefined;
|
||||
}
|
||||
|
||||
interface AddressInfo {
|
||||
address: string;
|
||||
family: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
// WebSocket Server
|
||||
class Server<
|
||||
T extends typeof WebSocket.WebSocket = typeof WebSocket.WebSocket,
|
||||
U extends typeof IncomingMessage = typeof IncomingMessage,
|
||||
> extends EventEmitter {
|
||||
options: ServerOptions<T, U>;
|
||||
path: string;
|
||||
clients: Set<InstanceType<T>>;
|
||||
|
||||
constructor(options?: ServerOptions<T, U>, callback?: () => void);
|
||||
|
||||
address(): AddressInfo | string | null;
|
||||
close(cb?: (err?: Error) => void): void;
|
||||
handleUpgrade(
|
||||
request: InstanceType<U>,
|
||||
socket: Duplex,
|
||||
upgradeHead: Buffer,
|
||||
callback: (client: InstanceType<T>, request: InstanceType<U>) => void,
|
||||
): void;
|
||||
shouldHandle(request: InstanceType<U>): boolean | Promise<boolean>;
|
||||
|
||||
// Events
|
||||
on(
|
||||
event: "connection",
|
||||
cb: (this: Server<T>, websocket: InstanceType<T>, request: InstanceType<U>) => void,
|
||||
): this;
|
||||
on(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||
on(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||
on(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||
on(
|
||||
event: "wsClientError",
|
||||
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||
): this;
|
||||
on(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||
|
||||
once(
|
||||
event: "connection",
|
||||
cb: (this: Server<T>, websocket: InstanceType<T>, request: InstanceType<U>) => void,
|
||||
): this;
|
||||
once(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||
once(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||
once(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||
once(
|
||||
event: "wsClientError",
|
||||
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||
): this;
|
||||
once(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||
|
||||
off(
|
||||
event: "connection",
|
||||
cb: (this: Server<T>, socket: InstanceType<T>, request: InstanceType<U>) => void,
|
||||
): this;
|
||||
off(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||
off(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||
off(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||
off(
|
||||
event: "wsClientError",
|
||||
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||
): this;
|
||||
off(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||
|
||||
addListener(event: "connection", cb: (websocket: InstanceType<T>, request: InstanceType<U>) => void): this;
|
||||
addListener(event: "error", cb: (error: Error) => void): this;
|
||||
addListener(event: "headers", cb: (headers: string[], request: InstanceType<U>) => void): this;
|
||||
addListener(event: "close" | "listening", cb: () => void): this;
|
||||
addListener(event: "wsClientError", cb: (error: Error, socket: Duplex, request: InstanceType<U>) => void): this;
|
||||
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
|
||||
removeListener(event: "connection", cb: (websocket: InstanceType<T>, request: InstanceType<U>) => void): this;
|
||||
removeListener(event: "error", cb: (error: Error) => void): this;
|
||||
removeListener(event: "headers", cb: (headers: string[], request: InstanceType<U>) => void): this;
|
||||
removeListener(event: "close" | "listening", cb: () => void): this;
|
||||
removeListener(
|
||||
event: "wsClientError",
|
||||
cb: (error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||
): this;
|
||||
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
}
|
||||
|
||||
const WebSocketServer: typeof Server;
|
||||
interface WebSocketServer extends Server {} // eslint-disable-line @typescript-eslint/no-empty-interface
|
||||
const WebSocket: typeof WebSocketAlias;
|
||||
interface WebSocket extends WebSocketAlias {} // eslint-disable-line @typescript-eslint/no-empty-interface
|
||||
|
||||
// WebSocket stream
|
||||
function createWebSocketStream(websocket: WebSocket, options?: DuplexOptions): Duplex;
|
||||
}
|
||||
|
||||
export = WebSocket;
|
||||
@@ -0,0 +1,38 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = handleCustomLevelsNamesOpts
|
||||
|
||||
/**
|
||||
* Parse a CSV string or options object that maps level
|
||||
* labels to level values.
|
||||
*
|
||||
* @param {string|object} cLevels An object mapping level
|
||||
* names to level values, e.g. `{ info: 30, debug: 65 }`, or a
|
||||
* CSV string in the format `level_name:level_value`, e.g.
|
||||
* `info:30,debug:65`.
|
||||
*
|
||||
* @returns {object} An object mapping levels names to level values
|
||||
* e.g. `{ info: 30, debug: 65 }`.
|
||||
*/
|
||||
function handleCustomLevelsNamesOpts (cLevels) {
|
||||
if (!cLevels) return {}
|
||||
|
||||
if (typeof cLevels === 'string') {
|
||||
return cLevels
|
||||
.split(',')
|
||||
.reduce((agg, value, idx) => {
|
||||
const [levelName, levelNum = idx] = value.split(':')
|
||||
agg[levelName.toLowerCase()] = levelNum
|
||||
return agg
|
||||
}, {})
|
||||
} else if (Object.prototype.toString.call(cLevels) === '[object Object]') {
|
||||
return Object
|
||||
.keys(cLevels)
|
||||
.reduce((agg, levelName) => {
|
||||
agg[levelName.toLowerCase()] = cLevels[levelName]
|
||||
return agg
|
||||
}, {})
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const es2017_intl: LibDefinition;
|
||||
@@ -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.dom_asynciterable = void 0;
|
||||
exports.dom_asynciterable = {
|
||||
libs: [],
|
||||
variables: [],
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
export { M as AgentReporter, l as BaseReporter, m as BenchmarkBuiltinReporters, n as BenchmarkReporter, o as BenchmarkReportsMap, K as BuiltinReporterOptions, N as BuiltinReporters, a0 as DefaultReporter, a2 as DotReporter, a4 as GithubActionsReporter, a6 as HangingProcessReporter, a9 as JUnitReporter, aa as JsonAssertionResult, ac as JsonReporter, ad as JsonTestResult, ae as JsonTestResults, M as MinimalReporter, ap as ReportedHookContext, aq as Reporter, ar as ReportersMap, ay as TapFlatReporter, az as TapReporter, aK as TestRunEndReason, aU as VerboseBenchmarkReporter, aV as VerboseReporter } from './chunks/reporters.d.DtoKVV2s.js';
|
||||
import '@vitest/runner';
|
||||
import '@vitest/utils';
|
||||
import './chunks/traces.d.D2T_R8rx.js';
|
||||
import 'node:stream';
|
||||
import 'vite';
|
||||
import './chunks/config.d.A1h_Y6Jt.js';
|
||||
import '@vitest/pretty-format';
|
||||
import '@vitest/snapshot';
|
||||
import '@vitest/utils/diff';
|
||||
import './chunks/browser.d.BcoexmFG.js';
|
||||
import './chunks/worker.d.ZpHpO4yb.js';
|
||||
import 'vite/module-runner';
|
||||
import './chunks/environment.d.CrsxCzP1.js';
|
||||
import './chunks/rpc.d.B_8sPU0w.js';
|
||||
import '@vitest/expect';
|
||||
import 'vitest/optional-types.js';
|
||||
import './chunks/benchmark.d.DAaHLpsq.js';
|
||||
import '@vitest/runner/utils';
|
||||
import 'tinybench';
|
||||
import '@vitest/mocker';
|
||||
import '@vitest/utils/source-map';
|
||||
import 'vitest/browser';
|
||||
import './chunks/coverage.d.BZtK59WP.js';
|
||||
import '@vitest/snapshot/manager';
|
||||
import 'node:console';
|
||||
import 'node:fs';
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,260 @@
|
||||
// Generated by LiveScript 1.6.0
|
||||
(function(){
|
||||
var ref$, id, find, sort, min, max, map, unlines, nameToRaw, dasherize, naturalJoin, wordWrap, wordwrap, getPreText, setHelpStyleDefaults, generateHelpForOption, generateHelp;
|
||||
ref$ = require('prelude-ls'), id = ref$.id, find = ref$.find, sort = ref$.sort, min = ref$.min, max = ref$.max, map = ref$.map, unlines = ref$.unlines;
|
||||
ref$ = require('./util'), nameToRaw = ref$.nameToRaw, dasherize = ref$.dasherize, naturalJoin = ref$.naturalJoin;
|
||||
wordWrap = require('word-wrap');
|
||||
wordwrap = function(a, b){
|
||||
var ref$, indent, width;
|
||||
ref$ = b === undefined
|
||||
? ['', a - 1]
|
||||
: [repeatString$(' ', a), b - a - 1], indent = ref$[0], width = ref$[1];
|
||||
return function(text){
|
||||
return wordWrap(text, {
|
||||
indent: indent,
|
||||
width: width,
|
||||
trim: true
|
||||
});
|
||||
};
|
||||
};
|
||||
getPreText = function(option, arg$, maxWidth){
|
||||
var mainName, shortNames, ref$, longNames, type, description, aliasSeparator, typeSeparator, initialIndent, names, namesString, namesStringLen, typeSeparatorString, typeSeparatorStringLen, wrap;
|
||||
mainName = option.option, shortNames = (ref$ = option.shortNames) != null
|
||||
? ref$
|
||||
: [], longNames = (ref$ = option.longNames) != null
|
||||
? ref$
|
||||
: [], type = option.type, description = option.description;
|
||||
aliasSeparator = arg$.aliasSeparator, typeSeparator = arg$.typeSeparator, initialIndent = arg$.initialIndent;
|
||||
if (option.negateName) {
|
||||
mainName = "no-" + mainName;
|
||||
if (longNames) {
|
||||
longNames = map(function(it){
|
||||
return "no-" + it;
|
||||
}, longNames);
|
||||
}
|
||||
}
|
||||
names = mainName.length === 1
|
||||
? [mainName].concat(shortNames, longNames)
|
||||
: shortNames.concat([mainName], longNames);
|
||||
namesString = map(nameToRaw, names).join(aliasSeparator);
|
||||
namesStringLen = namesString.length;
|
||||
typeSeparatorString = mainName === 'NUM' ? '::' : typeSeparator;
|
||||
typeSeparatorStringLen = typeSeparatorString.length;
|
||||
if (maxWidth != null && !option.boolean && initialIndent + namesStringLen + typeSeparatorStringLen + type.length > maxWidth) {
|
||||
wrap = wordwrap(initialIndent + namesStringLen + typeSeparatorStringLen, maxWidth);
|
||||
return namesString + "" + typeSeparatorString + wrap(type).replace(/^\s+/, '');
|
||||
} else {
|
||||
return namesString + "" + (option.boolean
|
||||
? ''
|
||||
: typeSeparatorString + "" + type);
|
||||
}
|
||||
};
|
||||
setHelpStyleDefaults = function(helpStyle){
|
||||
helpStyle.aliasSeparator == null && (helpStyle.aliasSeparator = ', ');
|
||||
helpStyle.typeSeparator == null && (helpStyle.typeSeparator = ' ');
|
||||
helpStyle.descriptionSeparator == null && (helpStyle.descriptionSeparator = ' ');
|
||||
helpStyle.initialIndent == null && (helpStyle.initialIndent = 2);
|
||||
helpStyle.secondaryIndent == null && (helpStyle.secondaryIndent = 4);
|
||||
helpStyle.maxPadFactor == null && (helpStyle.maxPadFactor = 1.5);
|
||||
};
|
||||
generateHelpForOption = function(getOption, arg$){
|
||||
var stdout, helpStyle, ref$;
|
||||
stdout = arg$.stdout, helpStyle = (ref$ = arg$.helpStyle) != null
|
||||
? ref$
|
||||
: {};
|
||||
setHelpStyleDefaults(helpStyle);
|
||||
return function(optionName){
|
||||
var maxWidth, wrap, option, e, pre, defaultString, restPositionalString, description, fullDescription, that, preDescription, descriptionString, exampleString, examples, seperator;
|
||||
maxWidth = stdout != null && stdout.isTTY ? stdout.columns - 1 : null;
|
||||
wrap = maxWidth ? wordwrap(maxWidth) : id;
|
||||
try {
|
||||
option = getOption(dasherize(optionName));
|
||||
} catch (e$) {
|
||||
e = e$;
|
||||
return e.message;
|
||||
}
|
||||
pre = getPreText(option, helpStyle);
|
||||
defaultString = option['default'] && !option.negateName ? "\ndefault: " + option['default'] : '';
|
||||
restPositionalString = option.restPositional ? 'Everything after this option is considered a positional argument, even if it looks like an option.' : '';
|
||||
description = option.longDescription || option.description && sentencize(option.description);
|
||||
fullDescription = description && restPositionalString
|
||||
? description + " " + restPositionalString
|
||||
: (that = description || restPositionalString) ? that : '';
|
||||
preDescription = 'description:';
|
||||
descriptionString = !fullDescription
|
||||
? ''
|
||||
: maxWidth && fullDescription.length - 1 - preDescription.length > maxWidth
|
||||
? "\n" + preDescription + "\n" + wrap(fullDescription)
|
||||
: "\n" + preDescription + " " + fullDescription;
|
||||
exampleString = (that = option.example) ? (examples = [].concat(that), examples.length > 1
|
||||
? "\nexamples:\n" + unlines(examples)
|
||||
: "\nexample: " + examples[0]) : '';
|
||||
seperator = defaultString || descriptionString || exampleString ? "\n" + repeatString$('=', pre.length) : '';
|
||||
return pre + "" + seperator + defaultString + descriptionString + exampleString;
|
||||
};
|
||||
};
|
||||
generateHelp = function(arg$){
|
||||
var options, prepend, append, helpStyle, ref$, stdout, aliasSeparator, typeSeparator, descriptionSeparator, maxPadFactor, initialIndent, secondaryIndent;
|
||||
options = arg$.options, prepend = arg$.prepend, append = arg$.append, helpStyle = (ref$ = arg$.helpStyle) != null
|
||||
? ref$
|
||||
: {}, stdout = arg$.stdout;
|
||||
setHelpStyleDefaults(helpStyle);
|
||||
aliasSeparator = helpStyle.aliasSeparator, typeSeparator = helpStyle.typeSeparator, descriptionSeparator = helpStyle.descriptionSeparator, maxPadFactor = helpStyle.maxPadFactor, initialIndent = helpStyle.initialIndent, secondaryIndent = helpStyle.secondaryIndent;
|
||||
return function(arg$){
|
||||
var ref$, showHidden, interpolate, maxWidth, output, out, data, optionCount, totalPreLen, preLens, i$, len$, item, that, pre, descParts, desc, preLen, sortedPreLens, maxPreLen, preLenMean, x, padAmount, descSepLen, fullWrapCount, partialWrapCount, descLen, totalLen, initialSpace, wrapAllFull, i, wrap;
|
||||
ref$ = arg$ != null
|
||||
? arg$
|
||||
: {}, showHidden = ref$.showHidden, interpolate = ref$.interpolate;
|
||||
maxWidth = stdout != null && stdout.isTTY ? stdout.columns - 1 : null;
|
||||
output = [];
|
||||
out = function(it){
|
||||
return output.push(it != null ? it : '');
|
||||
};
|
||||
if (prepend) {
|
||||
out(interpolate ? interp(prepend, interpolate) : prepend);
|
||||
out();
|
||||
}
|
||||
data = [];
|
||||
optionCount = 0;
|
||||
totalPreLen = 0;
|
||||
preLens = [];
|
||||
for (i$ = 0, len$ = (ref$ = options).length; i$ < len$; ++i$) {
|
||||
item = ref$[i$];
|
||||
if (showHidden || !item.hidden) {
|
||||
if (that = item.heading) {
|
||||
data.push({
|
||||
type: 'heading',
|
||||
value: that
|
||||
});
|
||||
} else {
|
||||
pre = getPreText(item, helpStyle, maxWidth);
|
||||
descParts = [];
|
||||
if ((that = item.description) != null) {
|
||||
descParts.push(that);
|
||||
}
|
||||
if (that = item['enum']) {
|
||||
descParts.push("either: " + naturalJoin(that));
|
||||
}
|
||||
if (item['default'] && !item.negateName) {
|
||||
descParts.push("default: " + item['default']);
|
||||
}
|
||||
desc = descParts.join(' - ');
|
||||
data.push({
|
||||
type: 'option',
|
||||
pre: pre,
|
||||
desc: desc,
|
||||
descLen: desc.length
|
||||
});
|
||||
preLen = pre.length;
|
||||
optionCount++;
|
||||
totalPreLen += preLen;
|
||||
preLens.push(preLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
sortedPreLens = sort(preLens);
|
||||
maxPreLen = sortedPreLens[sortedPreLens.length - 1];
|
||||
preLenMean = initialIndent + totalPreLen / optionCount;
|
||||
x = optionCount > 2 ? min(preLenMean * maxPadFactor, maxPreLen) : maxPreLen;
|
||||
for (i$ = sortedPreLens.length - 1; i$ >= 0; --i$) {
|
||||
preLen = sortedPreLens[i$];
|
||||
if (preLen <= x) {
|
||||
padAmount = preLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
descSepLen = descriptionSeparator.length;
|
||||
if (maxWidth != null) {
|
||||
fullWrapCount = 0;
|
||||
partialWrapCount = 0;
|
||||
for (i$ = 0, len$ = data.length; i$ < len$; ++i$) {
|
||||
item = data[i$];
|
||||
if (item.type === 'option') {
|
||||
pre = item.pre, desc = item.desc, descLen = item.descLen;
|
||||
if (descLen === 0) {
|
||||
item.wrap = 'none';
|
||||
} else {
|
||||
preLen = max(padAmount, pre.length) + initialIndent + descSepLen;
|
||||
totalLen = preLen + descLen;
|
||||
if (totalLen > maxWidth) {
|
||||
if (descLen / 2.5 > maxWidth - preLen) {
|
||||
fullWrapCount++;
|
||||
item.wrap = 'full';
|
||||
} else {
|
||||
partialWrapCount++;
|
||||
item.wrap = 'partial';
|
||||
}
|
||||
} else {
|
||||
item.wrap = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
initialSpace = repeatString$(' ', initialIndent);
|
||||
wrapAllFull = optionCount > 1 && fullWrapCount + partialWrapCount * 0.5 > optionCount * 0.5;
|
||||
for (i$ = 0, len$ = data.length; i$ < len$; ++i$) {
|
||||
i = i$;
|
||||
item = data[i$];
|
||||
if (item.type === 'heading') {
|
||||
if (i !== 0) {
|
||||
out();
|
||||
}
|
||||
out(item.value + ":");
|
||||
} else {
|
||||
pre = item.pre, desc = item.desc, descLen = item.descLen, wrap = item.wrap;
|
||||
if (maxWidth != null) {
|
||||
if (wrapAllFull || wrap === 'full') {
|
||||
wrap = wordwrap(initialIndent + secondaryIndent, maxWidth);
|
||||
out(initialSpace + "" + pre + "\n" + wrap(desc));
|
||||
continue;
|
||||
} else if (wrap === 'partial') {
|
||||
wrap = wordwrap(initialIndent + descSepLen + max(padAmount, pre.length), maxWidth);
|
||||
out(initialSpace + "" + pad(pre, padAmount) + descriptionSeparator + wrap(desc).replace(/^\s+/, ''));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (descLen === 0) {
|
||||
out(initialSpace + "" + pre);
|
||||
} else {
|
||||
out(initialSpace + "" + pad(pre, padAmount) + descriptionSeparator + desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (append) {
|
||||
out();
|
||||
out(interpolate ? interp(append, interpolate) : append);
|
||||
}
|
||||
return unlines(output);
|
||||
};
|
||||
};
|
||||
function pad(str, num){
|
||||
var len, padAmount;
|
||||
len = str.length;
|
||||
padAmount = num - len;
|
||||
return str + "" + repeatString$(' ', padAmount > 0 ? padAmount : 0);
|
||||
}
|
||||
function sentencize(str){
|
||||
var first, rest, period;
|
||||
first = str.charAt(0).toUpperCase();
|
||||
rest = str.slice(1);
|
||||
period = /[\.!\?]$/.test(str) ? '' : '.';
|
||||
return first + "" + rest + period;
|
||||
}
|
||||
function interp(string, object){
|
||||
return string.replace(/{{([a-zA-Z$_][a-zA-Z$_0-9]*)}}/g, function(arg$, key){
|
||||
var ref$;
|
||||
return (ref$ = object[key]) != null
|
||||
? ref$
|
||||
: "{{" + key + "}}";
|
||||
});
|
||||
}
|
||||
module.exports = {
|
||||
generateHelp: generateHelp,
|
||||
generateHelpForOption: generateHelpForOption
|
||||
};
|
||||
function repeatString$(str, n){
|
||||
for (var r = ''; n > 0; (n >>= 1) && (str += str)) if (n & 1) r += str;
|
||||
return r;
|
||||
}
|
||||
}).call(this);
|
||||
@@ -0,0 +1,223 @@
|
||||
'use strict'
|
||||
|
||||
const {
|
||||
MAX_SAFE_COMPONENT_LENGTH,
|
||||
MAX_SAFE_BUILD_LENGTH,
|
||||
MAX_LENGTH,
|
||||
} = require('./constants')
|
||||
const debug = require('./debug')
|
||||
exports = module.exports = {}
|
||||
|
||||
// The actual regexps go on exports.re
|
||||
const re = exports.re = []
|
||||
const safeRe = exports.safeRe = []
|
||||
const src = exports.src = []
|
||||
const safeSrc = exports.safeSrc = []
|
||||
const t = exports.t = {}
|
||||
let R = 0
|
||||
|
||||
const LETTERDASHNUMBER = '[a-zA-Z0-9-]'
|
||||
|
||||
// Replace some greedy regex tokens to prevent regex dos issues. These regex are
|
||||
// used internally via the safeRe object since all inputs in this library get
|
||||
// normalized first to trim and collapse all extra whitespace. The original
|
||||
// regexes are exported for userland consumption and lower level usage. A
|
||||
// future breaking change could export the safer regex only with a note that
|
||||
// all input should have extra whitespace removed.
|
||||
const safeRegexReplacements = [
|
||||
['\\s', 1],
|
||||
['\\d', MAX_LENGTH],
|
||||
[LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
|
||||
]
|
||||
|
||||
const makeSafeRegex = (value) => {
|
||||
for (const [token, max] of safeRegexReplacements) {
|
||||
value = value
|
||||
.split(`${token}*`).join(`${token}{0,${max}}`)
|
||||
.split(`${token}+`).join(`${token}{1,${max}}`)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
const createToken = (name, value, isGlobal) => {
|
||||
const safe = makeSafeRegex(value)
|
||||
const index = R++
|
||||
debug(name, index, value)
|
||||
t[name] = index
|
||||
src[index] = value
|
||||
safeSrc[index] = safe
|
||||
re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
|
||||
safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined)
|
||||
}
|
||||
|
||||
// The following Regular Expressions can be used for tokenizing,
|
||||
// validating, and parsing SemVer version strings.
|
||||
|
||||
// ## Numeric Identifier
|
||||
// A single `0`, or a non-zero digit followed by zero or more digits.
|
||||
|
||||
createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*')
|
||||
createToken('NUMERICIDENTIFIERLOOSE', '\\d+')
|
||||
|
||||
// ## Non-numeric Identifier
|
||||
// Zero or more digits, followed by a letter or hyphen, and then zero or
|
||||
// more letters, digits, or hyphens.
|
||||
|
||||
createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`)
|
||||
|
||||
// ## Main Version
|
||||
// Three dot-separated numeric identifiers.
|
||||
|
||||
createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
|
||||
`(${src[t.NUMERICIDENTIFIER]})\\.` +
|
||||
`(${src[t.NUMERICIDENTIFIER]})`)
|
||||
|
||||
createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
|
||||
`(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
|
||||
`(${src[t.NUMERICIDENTIFIERLOOSE]})`)
|
||||
|
||||
// ## Pre-release Version Identifier
|
||||
// A numeric identifier, or a non-numeric identifier.
|
||||
// Non-numeric identifiers include numeric identifiers but can be longer.
|
||||
// Therefore non-numeric identifiers must go first.
|
||||
|
||||
createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER]
|
||||
}|${src[t.NUMERICIDENTIFIER]})`)
|
||||
|
||||
createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NONNUMERICIDENTIFIER]
|
||||
}|${src[t.NUMERICIDENTIFIERLOOSE]})`)
|
||||
|
||||
// ## Pre-release Version
|
||||
// Hyphen, followed by one or more dot-separated pre-release version
|
||||
// identifiers.
|
||||
|
||||
createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
|
||||
}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`)
|
||||
|
||||
createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
|
||||
}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`)
|
||||
|
||||
// ## Build Metadata Identifier
|
||||
// Any combination of digits, letters, or hyphens.
|
||||
|
||||
createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`)
|
||||
|
||||
// ## Build Metadata
|
||||
// Plus sign, followed by one or more period-separated build metadata
|
||||
// identifiers.
|
||||
|
||||
createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
|
||||
}(?:\\.${src[t.BUILDIDENTIFIER]})*))`)
|
||||
|
||||
// ## Full Version String
|
||||
// A main version, followed optionally by a pre-release version and
|
||||
// build metadata.
|
||||
|
||||
// Note that the only major, minor, patch, and pre-release sections of
|
||||
// the version string are capturing groups. The build metadata is not a
|
||||
// capturing group, because it should not ever be used in version
|
||||
// comparison.
|
||||
|
||||
createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
|
||||
}${src[t.PRERELEASE]}?${
|
||||
src[t.BUILD]}?`)
|
||||
|
||||
createToken('FULL', `^${src[t.FULLPLAIN]}$`)
|
||||
|
||||
// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
|
||||
// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
|
||||
// common in the npm registry.
|
||||
createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
|
||||
}${src[t.PRERELEASELOOSE]}?${
|
||||
src[t.BUILD]}?`)
|
||||
|
||||
createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`)
|
||||
|
||||
createToken('GTLT', '((?:<|>)?=?)')
|
||||
|
||||
// Something like "2.*" or "1.2.x".
|
||||
// Note that "x.x" is a valid xRange identifier, meaning "any version"
|
||||
// Only the first item is strictly required.
|
||||
createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`)
|
||||
createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`)
|
||||
|
||||
createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
|
||||
`(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
|
||||
`(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
|
||||
`(?:${src[t.PRERELEASE]})?${
|
||||
src[t.BUILD]}?` +
|
||||
`)?)?`)
|
||||
|
||||
createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
||||
`(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
||||
`(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
||||
`(?:${src[t.PRERELEASELOOSE]})?${
|
||||
src[t.BUILD]}?` +
|
||||
`)?)?`)
|
||||
|
||||
createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`)
|
||||
createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`)
|
||||
|
||||
// Coercion.
|
||||
// Extract anything that could conceivably be a part of a valid semver
|
||||
createToken('COERCEPLAIN', `${'(^|[^\\d])' +
|
||||
'(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
|
||||
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
|
||||
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`)
|
||||
createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`)
|
||||
createToken('COERCEFULL', src[t.COERCEPLAIN] +
|
||||
`(?:${src[t.PRERELEASE]})?` +
|
||||
`(?:${src[t.BUILD]})?` +
|
||||
`(?:$|[^\\d])`)
|
||||
createToken('COERCERTL', src[t.COERCE], true)
|
||||
createToken('COERCERTLFULL', src[t.COERCEFULL], true)
|
||||
|
||||
// Tilde ranges.
|
||||
// Meaning is "reasonably at or greater than"
|
||||
createToken('LONETILDE', '(?:~>?)')
|
||||
|
||||
createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true)
|
||||
exports.tildeTrimReplace = '$1~'
|
||||
|
||||
createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`)
|
||||
createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`)
|
||||
|
||||
// Caret ranges.
|
||||
// Meaning is "at least and backwards compatible with"
|
||||
createToken('LONECARET', '(?:\\^)')
|
||||
|
||||
createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true)
|
||||
exports.caretTrimReplace = '$1^'
|
||||
|
||||
createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`)
|
||||
createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`)
|
||||
|
||||
// A simple gt/lt/eq thing, or just "" to indicate "any version"
|
||||
createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`)
|
||||
createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`)
|
||||
|
||||
// An expression to strip any whitespace between the gtlt and the thing
|
||||
// it modifies, so that `> 1.2.3` ==> `>1.2.3`
|
||||
createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
|
||||
}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true)
|
||||
exports.comparatorTrimReplace = '$1$2$3'
|
||||
|
||||
// Something like `1.2.3 - 1.2.4`
|
||||
// Note that these all use the loose form, because they'll be
|
||||
// checked against either the strict or loose comparator form
|
||||
// later.
|
||||
createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
|
||||
`\\s+-\\s+` +
|
||||
`(${src[t.XRANGEPLAIN]})` +
|
||||
`\\s*$`)
|
||||
|
||||
createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
|
||||
`\\s+-\\s+` +
|
||||
`(${src[t.XRANGEPLAINLOOSE]})` +
|
||||
`\\s*$`)
|
||||
|
||||
// Star ranges basically just allow anything at all.
|
||||
createToken('STAR', '(<|>)?=?\\s*\\*')
|
||||
// >=0.0.0 is like a star
|
||||
createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$')
|
||||
createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$')
|
||||
@@ -0,0 +1,5 @@
|
||||
var assertClassBrand = require("./assertClassBrand.js");
|
||||
function _classCheckPrivateStaticAccess(s, a, r) {
|
||||
return assertClassBrand(a, s, r);
|
||||
}
|
||||
module.exports = _classCheckPrivateStaticAccess, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { TSESTree } from '@typescript-eslint/types';
|
||||
import { DefinitionBase } from './DefinitionBase';
|
||||
import { DefinitionType } from './DefinitionType';
|
||||
export declare class ImportBindingDefinition extends DefinitionBase<DefinitionType.ImportBinding, TSESTree.ImportDefaultSpecifier | TSESTree.ImportNamespaceSpecifier | TSESTree.ImportSpecifier | TSESTree.TSImportEqualsDeclaration, TSESTree.ImportDeclaration | TSESTree.TSImportEqualsDeclaration, TSESTree.Identifier> {
|
||||
readonly isTypeDefinition = true;
|
||||
readonly isVariableDefinition = true;
|
||||
constructor(name: TSESTree.Identifier, node: TSESTree.TSImportEqualsDeclaration, decl: TSESTree.TSImportEqualsDeclaration);
|
||||
constructor(name: TSESTree.Identifier, node: Exclude<ImportBindingDefinition['node'], TSESTree.TSImportEqualsDeclaration>, decl: TSESTree.ImportDeclaration);
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
"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: "حروف", verb: "ہونا" },
|
||||
file: { unit: "بائٹس", verb: "ہونا" },
|
||||
array: { unit: "آئٹمز", verb: "ہونا" },
|
||||
set: { unit: "آئٹمز", verb: "ہونا" },
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "ان پٹ",
|
||||
email: "ای میل ایڈریس",
|
||||
url: "یو آر ایل",
|
||||
emoji: "ایموجی",
|
||||
uuid: "یو یو آئی ڈی",
|
||||
uuidv4: "یو یو آئی ڈی وی 4",
|
||||
uuidv6: "یو یو آئی ڈی وی 6",
|
||||
nanoid: "نینو آئی ڈی",
|
||||
guid: "جی یو آئی ڈی",
|
||||
cuid: "سی یو آئی ڈی",
|
||||
cuid2: "سی یو آئی ڈی 2",
|
||||
ulid: "یو ایل آئی ڈی",
|
||||
xid: "ایکس آئی ڈی",
|
||||
ksuid: "کے ایس یو آئی ڈی",
|
||||
datetime: "آئی ایس او ڈیٹ ٹائم",
|
||||
date: "آئی ایس او تاریخ",
|
||||
time: "آئی ایس او وقت",
|
||||
duration: "آئی ایس او مدت",
|
||||
ipv4: "آئی پی وی 4 ایڈریس",
|
||||
ipv6: "آئی پی وی 6 ایڈریس",
|
||||
cidrv4: "آئی پی وی 4 رینج",
|
||||
cidrv6: "آئی پی وی 6 رینج",
|
||||
base64: "بیس 64 ان کوڈڈ سٹرنگ",
|
||||
base64url: "بیس 64 یو آر ایل ان کوڈڈ سٹرنگ",
|
||||
json_string: "جے ایس او این سٹرنگ",
|
||||
e164: "ای 164 نمبر",
|
||||
jwt: "جے ڈبلیو ٹی",
|
||||
template_literal: "ان پٹ",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
number: "نمبر",
|
||||
array: "آرے",
|
||||
null: "نل",
|
||||
};
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `غلط ان پٹ: instanceof ${issue.expected} متوقع تھا، ${received} موصول ہوا`;
|
||||
}
|
||||
return `غلط ان پٹ: ${expected} متوقع تھا، ${received} موصول ہوا`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `غلط ان پٹ: ${util.stringifyPrimitive(issue.values[0])} متوقع تھا`;
|
||||
return `غلط آپشن: ${util.joinValues(issue.values, "|")} میں سے ایک متوقع تھا`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `بہت بڑا: ${issue.origin ?? "ویلیو"} کے ${adj}${issue.maximum.toString()} ${sizing.unit ?? "عناصر"} ہونے متوقع تھے`;
|
||||
return `بہت بڑا: ${issue.origin ?? "ویلیو"} کا ${adj}${issue.maximum.toString()} ہونا متوقع تھا`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `بہت چھوٹا: ${issue.origin} کے ${adj}${issue.minimum.toString()} ${sizing.unit} ہونے متوقع تھے`;
|
||||
}
|
||||
return `بہت چھوٹا: ${issue.origin} کا ${adj}${issue.minimum.toString()} ہونا متوقع تھا`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with") {
|
||||
return `غلط سٹرنگ: "${_issue.prefix}" سے شروع ہونا چاہیے`;
|
||||
}
|
||||
if (_issue.format === "ends_with")
|
||||
return `غلط سٹرنگ: "${_issue.suffix}" پر ختم ہونا چاہیے`;
|
||||
if (_issue.format === "includes")
|
||||
return `غلط سٹرنگ: "${_issue.includes}" شامل ہونا چاہیے`;
|
||||
if (_issue.format === "regex")
|
||||
return `غلط سٹرنگ: پیٹرن ${_issue.pattern} سے میچ ہونا چاہیے`;
|
||||
return `غلط ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `غلط نمبر: ${issue.divisor} کا مضاعف ہونا چاہیے`;
|
||||
case "unrecognized_keys":
|
||||
return `غیر تسلیم شدہ کی${issue.keys.length > 1 ? "ز" : ""}: ${util.joinValues(issue.keys, "، ")}`;
|
||||
case "invalid_key":
|
||||
return `${issue.origin} میں غلط کی`;
|
||||
case "invalid_union":
|
||||
return "غلط ان پٹ";
|
||||
case "invalid_element":
|
||||
return `${issue.origin} میں غلط ویلیو`;
|
||||
default:
|
||||
return `غلط ان پٹ`;
|
||||
}
|
||||
};
|
||||
};
|
||||
function default_1() {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
module.exports = exports.default;
|
||||
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function (it) {
|
||||
const { pluginName, ruleId } = it;
|
||||
|
||||
return `
|
||||
A configuration object specifies rule "${ruleId}", but could not find plugin "${pluginName}".
|
||||
|
||||
Common causes of this problem include:
|
||||
|
||||
1. The "${pluginName}" plugin is not defined in your configuration file.
|
||||
2. The "${pluginName}" plugin is not defined within the same configuration object in which the "${ruleId}" rule is applied.
|
||||
`.trimStart();
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Parser } from "../index.js";
|
||||
|
||||
export declare const parsers: {
|
||||
typescript: Parser;
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
const file12 = require("./file12.js")
|
||||
|
||||
file12()
|
||||
@@ -0,0 +1,102 @@
|
||||
const MINIMUM_SLOT_PER_EPOCH = 32;
|
||||
|
||||
// Returns the number of trailing zeros in the binary representation of self.
|
||||
function trailingZeros(n: number) {
|
||||
let trailingZeros = 0;
|
||||
while (n > 1) {
|
||||
n /= 2;
|
||||
trailingZeros++;
|
||||
}
|
||||
return trailingZeros;
|
||||
}
|
||||
|
||||
// Returns the smallest power of two greater than or equal to n
|
||||
function nextPowerOfTwo(n: number) {
|
||||
if (n === 0) return 1;
|
||||
n--;
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
n |= n >> 32;
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Epoch schedule
|
||||
* (see https://docs.solana.com/terminology#epoch)
|
||||
* Can be retrieved with the {@link Connection.getEpochSchedule} method
|
||||
*/
|
||||
export class EpochSchedule {
|
||||
/** The maximum number of slots in each epoch */
|
||||
public slotsPerEpoch: number;
|
||||
/** The number of slots before beginning of an epoch to calculate a leader schedule for that epoch */
|
||||
public leaderScheduleSlotOffset: number;
|
||||
/** Indicates whether epochs start short and grow */
|
||||
public warmup: boolean;
|
||||
/** The first epoch with `slotsPerEpoch` slots */
|
||||
public firstNormalEpoch: number;
|
||||
/** The first slot of `firstNormalEpoch` */
|
||||
public firstNormalSlot: number;
|
||||
|
||||
constructor(
|
||||
slotsPerEpoch: number,
|
||||
leaderScheduleSlotOffset: number,
|
||||
warmup: boolean,
|
||||
firstNormalEpoch: number,
|
||||
firstNormalSlot: number,
|
||||
) {
|
||||
this.slotsPerEpoch = slotsPerEpoch;
|
||||
this.leaderScheduleSlotOffset = leaderScheduleSlotOffset;
|
||||
this.warmup = warmup;
|
||||
this.firstNormalEpoch = firstNormalEpoch;
|
||||
this.firstNormalSlot = firstNormalSlot;
|
||||
}
|
||||
|
||||
getEpoch(slot: number): number {
|
||||
return this.getEpochAndSlotIndex(slot)[0];
|
||||
}
|
||||
|
||||
getEpochAndSlotIndex(slot: number): [number, number] {
|
||||
if (slot < this.firstNormalSlot) {
|
||||
const epoch =
|
||||
trailingZeros(nextPowerOfTwo(slot + MINIMUM_SLOT_PER_EPOCH + 1)) -
|
||||
trailingZeros(MINIMUM_SLOT_PER_EPOCH) -
|
||||
1;
|
||||
|
||||
const epochLen = this.getSlotsInEpoch(epoch);
|
||||
const slotIndex = slot - (epochLen - MINIMUM_SLOT_PER_EPOCH);
|
||||
return [epoch, slotIndex];
|
||||
} else {
|
||||
const normalSlotIndex = slot - this.firstNormalSlot;
|
||||
const normalEpochIndex = Math.floor(normalSlotIndex / this.slotsPerEpoch);
|
||||
const epoch = this.firstNormalEpoch + normalEpochIndex;
|
||||
const slotIndex = normalSlotIndex % this.slotsPerEpoch;
|
||||
return [epoch, slotIndex];
|
||||
}
|
||||
}
|
||||
|
||||
getFirstSlotInEpoch(epoch: number): number {
|
||||
if (epoch <= this.firstNormalEpoch) {
|
||||
return (Math.pow(2, epoch) - 1) * MINIMUM_SLOT_PER_EPOCH;
|
||||
} else {
|
||||
return (
|
||||
(epoch - this.firstNormalEpoch) * this.slotsPerEpoch +
|
||||
this.firstNormalSlot
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getLastSlotInEpoch(epoch: number): number {
|
||||
return this.getFirstSlotInEpoch(epoch) + this.getSlotsInEpoch(epoch) - 1;
|
||||
}
|
||||
|
||||
getSlotsInEpoch(epoch: number) {
|
||||
if (epoch < this.firstNormalEpoch) {
|
||||
return Math.pow(2, epoch + trailingZeros(MINIMUM_SLOT_PER_EPOCH));
|
||||
} else {
|
||||
return this.slotsPerEpoch;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const util_1 = require("../util");
|
||||
exports.default = (0, util_1.createRule)({
|
||||
name: 'consistent-indexed-object-style',
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Require or disallow the `Record` type',
|
||||
recommended: 'stylistic',
|
||||
},
|
||||
fixable: 'code',
|
||||
// eslint-disable-next-line eslint-plugin/require-meta-has-suggestions -- suggestions are exposed through a helper.
|
||||
hasSuggestions: true,
|
||||
messages: {
|
||||
preferIndexSignature: 'An index signature is preferred over a record.',
|
||||
preferIndexSignatureSuggestion: 'Change into an index signature instead of a record.',
|
||||
preferRecord: 'A record is preferred over an index signature.',
|
||||
preferRecordSuggestion: 'Change into a record instead of an index signature.',
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
type: 'string',
|
||||
description: 'Which indexed object syntax to prefer.',
|
||||
enum: ['record', 'index-signature'],
|
||||
},
|
||||
],
|
||||
},
|
||||
defaultOptions: ['record'],
|
||||
create(context, [mode]) {
|
||||
// The fixers rebuild the type from the text of a few sub-nodes, so a
|
||||
// comment inside `node` but outside all of those preserved sub-nodes would
|
||||
// be dropped by the fix. Returns true when at least one such comment exists.
|
||||
function hasUnpreservedComments(node, ...preserved) {
|
||||
return context.sourceCode
|
||||
.getCommentsInside(node)
|
||||
.some(comment => preserved.every(target => target == null ||
|
||||
comment.range[0] < target.range[0] ||
|
||||
comment.range[1] > target.range[1]));
|
||||
}
|
||||
function checkMembers(members, node, parentId, prefix, postfix, safeFix = true) {
|
||||
if (members.length !== 1) {
|
||||
return;
|
||||
}
|
||||
const [member] = members;
|
||||
if (member.type !== utils_1.AST_NODE_TYPES.TSIndexSignature) {
|
||||
return;
|
||||
}
|
||||
const parameter = member.parameters.at(0);
|
||||
if (parameter?.type !== utils_1.AST_NODE_TYPES.Identifier) {
|
||||
return;
|
||||
}
|
||||
const keyType = parameter.typeAnnotation;
|
||||
if (!keyType) {
|
||||
return;
|
||||
}
|
||||
const valueType = member.typeAnnotation;
|
||||
if (!valueType) {
|
||||
return;
|
||||
}
|
||||
if (parentId) {
|
||||
const scope = context.sourceCode.getScope(parentId);
|
||||
const superVar = utils_1.ASTUtils.findVariable(scope, parentId.name);
|
||||
if (superVar &&
|
||||
isDeeplyReferencingType(node, superVar, new Set([parentId]))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'preferRecord',
|
||||
...(0, util_1.getFixOrSuggest)({
|
||||
fixOrSuggest: !safeFix
|
||||
? 'none'
|
||||
: hasUnpreservedComments(node, keyType.typeAnnotation, valueType.typeAnnotation)
|
||||
? 'suggest'
|
||||
: 'fix',
|
||||
suggestion: {
|
||||
messageId: 'preferRecordSuggestion',
|
||||
fix: (fixer) => {
|
||||
const key = context.sourceCode.getText(keyType.typeAnnotation);
|
||||
const value = context.sourceCode.getText(valueType.typeAnnotation);
|
||||
const record = member.readonly
|
||||
? `Readonly<Record<${key}, ${value}>>`
|
||||
: `Record<${key}, ${value}>`;
|
||||
return fixer.replaceText(node, `${prefix}${record}${postfix}`);
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
return {
|
||||
...(mode === 'index-signature' && {
|
||||
TSTypeReference(node) {
|
||||
const typeName = node.typeName;
|
||||
if (typeName.type !== utils_1.AST_NODE_TYPES.Identifier) {
|
||||
return;
|
||||
}
|
||||
if (typeName.name !== 'Record') {
|
||||
return;
|
||||
}
|
||||
const params = node.typeArguments?.params;
|
||||
if (params?.length !== 2) {
|
||||
return;
|
||||
}
|
||||
const indexParam = params[0];
|
||||
const shouldFix = indexParam.type === utils_1.AST_NODE_TYPES.TSStringKeyword ||
|
||||
indexParam.type === utils_1.AST_NODE_TYPES.TSNumberKeyword ||
|
||||
indexParam.type === utils_1.AST_NODE_TYPES.TSSymbolKeyword;
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'preferIndexSignature',
|
||||
...(0, util_1.getFixOrSuggest)({
|
||||
fixOrSuggest: shouldFix && !hasUnpreservedComments(node, params[0], params[1])
|
||||
? 'fix'
|
||||
: 'suggest',
|
||||
suggestion: {
|
||||
messageId: 'preferIndexSignatureSuggestion',
|
||||
fix: fixer => {
|
||||
const key = context.sourceCode.getText(params[0]);
|
||||
const type = context.sourceCode.getText(params[1]);
|
||||
return fixer.replaceText(node, `{ [key: ${key}]: ${type} }`);
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
},
|
||||
}),
|
||||
...(mode === 'record' && {
|
||||
TSInterfaceDeclaration(node) {
|
||||
let genericTypes = '';
|
||||
if (node.typeParameters?.params.length) {
|
||||
genericTypes = `<${node.typeParameters.params
|
||||
.map(p => context.sourceCode.getText(p))
|
||||
.join(', ')}>`;
|
||||
}
|
||||
checkMembers(node.body.body, node, node.id, `type ${node.id.name}${genericTypes} = `, ';', !node.extends.length &&
|
||||
node.parent.type !== utils_1.AST_NODE_TYPES.ExportDefaultDeclaration);
|
||||
},
|
||||
TSMappedType(node) {
|
||||
const key = node.key;
|
||||
const scope = context.sourceCode.getScope(key);
|
||||
const scopeManagerKey = (0, util_1.nullThrows)(scope.variables.find(value => value.name === key.name && value.isTypeVariable), 'key type parameter must be a defined type variable in its scope');
|
||||
// If the key is used to compute the value, we can't convert to a Record.
|
||||
if (scopeManagerKey.references.some(reference => reference.isTypeReference)) {
|
||||
return;
|
||||
}
|
||||
const constraint = node.constraint;
|
||||
if (constraint.type === utils_1.AST_NODE_TYPES.TSTypeOperator &&
|
||||
constraint.operator === 'keyof' &&
|
||||
!(0, util_1.isParenthesized)(constraint, context.sourceCode)) {
|
||||
// This is a weird special case, since modifiers are preserved by
|
||||
// the mapped type, but not by the Record type. So this type is not,
|
||||
// in general, equivalent to a Record type.
|
||||
return;
|
||||
}
|
||||
// If the mapped type is circular, we can't convert it to a Record.
|
||||
const parentId = findParentDeclaration(node)?.id;
|
||||
if (parentId) {
|
||||
const scope = context.sourceCode.getScope(key);
|
||||
const superVar = utils_1.ASTUtils.findVariable(scope, parentId.name);
|
||||
if (superVar) {
|
||||
const isCircular = isDeeplyReferencingType(node.parent, superVar, new Set([parentId]));
|
||||
if (isCircular) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'preferRecord',
|
||||
...(0, util_1.getFixOrSuggest)({
|
||||
// There's no builtin Mutable<T> type, so a `-readonly` mapped
|
||||
// type can't be represented as a Record and is left untouched.
|
||||
fixOrSuggest: node.readonly === '-'
|
||||
? 'none'
|
||||
: hasUnpreservedComments(node, constraint, node.typeAnnotation)
|
||||
? 'suggest'
|
||||
: 'fix',
|
||||
suggestion: {
|
||||
messageId: 'preferRecordSuggestion',
|
||||
fix: (fixer) => {
|
||||
const keyType = context.sourceCode.getText(constraint);
|
||||
const valueType = node.typeAnnotation
|
||||
? context.sourceCode.getText(node.typeAnnotation)
|
||||
: 'any';
|
||||
let recordText = `Record<${keyType}, ${valueType}>`;
|
||||
if (node.optional === '+' || node.optional === true) {
|
||||
recordText = `Partial<${recordText}>`;
|
||||
}
|
||||
else if (node.optional === '-') {
|
||||
recordText = `Required<${recordText}>`;
|
||||
}
|
||||
if (node.readonly === '+' || node.readonly === true) {
|
||||
recordText = `Readonly<${recordText}>`;
|
||||
}
|
||||
return fixer.replaceText(node, recordText);
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
},
|
||||
TSTypeLiteral(node) {
|
||||
const parent = findParentDeclaration(node);
|
||||
checkMembers(node.members, node, parent?.id, '', '');
|
||||
},
|
||||
}),
|
||||
};
|
||||
},
|
||||
});
|
||||
function findParentDeclaration(node) {
|
||||
if (node.parent && node.parent.type !== utils_1.AST_NODE_TYPES.TSTypeAnnotation) {
|
||||
if (node.parent.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration) {
|
||||
return node.parent;
|
||||
}
|
||||
return findParentDeclaration(node.parent);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function isDeeplyReferencingType(node, superVar, visited) {
|
||||
if (visited.has(node)) {
|
||||
// something on the chain is circular but it's not the reference being checked
|
||||
return false;
|
||||
}
|
||||
visited.add(node);
|
||||
switch (node.type) {
|
||||
case utils_1.AST_NODE_TYPES.TSTypeLiteral:
|
||||
return node.members.some(member => isDeeplyReferencingType(member, superVar, visited));
|
||||
case utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration:
|
||||
return isDeeplyReferencingType(node.typeAnnotation, superVar, visited);
|
||||
case utils_1.AST_NODE_TYPES.TSIndexedAccessType:
|
||||
return [node.indexType, node.objectType].some(type => isDeeplyReferencingType(type, superVar, visited));
|
||||
case utils_1.AST_NODE_TYPES.TSMappedType:
|
||||
if (node.typeAnnotation) {
|
||||
return isDeeplyReferencingType(node.typeAnnotation, superVar, visited);
|
||||
}
|
||||
break;
|
||||
case utils_1.AST_NODE_TYPES.TSConditionalType:
|
||||
return [
|
||||
node.checkType,
|
||||
node.extendsType,
|
||||
node.falseType,
|
||||
node.trueType,
|
||||
].some(type => isDeeplyReferencingType(type, superVar, visited));
|
||||
case utils_1.AST_NODE_TYPES.TSUnionType:
|
||||
case utils_1.AST_NODE_TYPES.TSIntersectionType:
|
||||
return node.types.some(type => isDeeplyReferencingType(type, superVar, visited));
|
||||
case utils_1.AST_NODE_TYPES.TSInterfaceDeclaration:
|
||||
return node.body.body.some(type => isDeeplyReferencingType(type, superVar, visited));
|
||||
case utils_1.AST_NODE_TYPES.TSTypeAnnotation:
|
||||
return isDeeplyReferencingType(node.typeAnnotation, superVar, visited);
|
||||
case utils_1.AST_NODE_TYPES.TSIndexSignature: {
|
||||
if (node.typeAnnotation) {
|
||||
return isDeeplyReferencingType(node.typeAnnotation, superVar, visited);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation: {
|
||||
return node.params.some(param => isDeeplyReferencingType(param, superVar, visited));
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.TSTypeReference: {
|
||||
if (isDeeplyReferencingType(node.typeName, superVar, visited)) {
|
||||
return true;
|
||||
}
|
||||
if (node.typeArguments &&
|
||||
isDeeplyReferencingType(node.typeArguments, superVar, visited)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.Identifier: {
|
||||
// check if the identifier is a reference of the type being checked
|
||||
if (superVar.references.some(ref => (0, util_1.isNodeEqual)(ref.identifier, node))) {
|
||||
return true;
|
||||
}
|
||||
// otherwise, follow its definition(s)
|
||||
const refVar = utils_1.ASTUtils.findVariable(superVar.scope, node.name);
|
||||
if (refVar) {
|
||||
return refVar.defs.some(def => isDeeplyReferencingType(def.node, superVar, visited));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,691 @@
|
||||
/**
|
||||
* @fileoverview Rule to replace assignment expressions with logical operator assignment
|
||||
* @author Daniel Martens
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
const astUtils = require("./utils/ast-utils.js");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const baseTypes = new Set(["Identifier", "Super", "ThisExpression"]);
|
||||
|
||||
/**
|
||||
* Returns true iff either "undefined" or a void expression (eg. "void 0")
|
||||
* @param {ASTNode} expression Expression to check
|
||||
* @param {import('eslint-scope').Scope} scope Scope of the expression
|
||||
* @returns {boolean} True iff "undefined" or "void ..."
|
||||
*/
|
||||
function isUndefined(expression, scope) {
|
||||
if (expression.type === "Identifier" && expression.name === "undefined") {
|
||||
return astUtils.isReferenceToGlobalVariable(scope, expression);
|
||||
}
|
||||
|
||||
return (
|
||||
expression.type === "UnaryExpression" &&
|
||||
expression.operator === "void" &&
|
||||
expression.argument.type === "Literal" &&
|
||||
expression.argument.value === 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff the reference is either an identifier or member expression
|
||||
* @param {ASTNode} expression Expression to check
|
||||
* @returns {boolean} True for identifiers and member expressions
|
||||
*/
|
||||
function isReference(expression) {
|
||||
return (
|
||||
(expression.type === "Identifier" && expression.name !== "undefined") ||
|
||||
expression.type === "MemberExpression"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff the expression checks for nullish with loose equals.
|
||||
* Examples: value == null, value == void 0
|
||||
* @param {ASTNode} expression Test condition
|
||||
* @param {import('eslint-scope').Scope} scope Scope of the expression
|
||||
* @returns {boolean} True iff implicit nullish comparison
|
||||
*/
|
||||
function isImplicitNullishComparison(expression, scope) {
|
||||
if (
|
||||
expression.type !== "BinaryExpression" ||
|
||||
expression.operator !== "=="
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const reference = isReference(expression.left) ? "left" : "right";
|
||||
const nullish = reference === "left" ? "right" : "left";
|
||||
|
||||
return (
|
||||
isReference(expression[reference]) &&
|
||||
(astUtils.isNullLiteral(expression[nullish]) ||
|
||||
isUndefined(expression[nullish], scope))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Condition with two equal comparisons.
|
||||
* @param {ASTNode} expression Condition
|
||||
* @returns {boolean} True iff matches ? === ? || ? === ?
|
||||
*/
|
||||
function isDoubleComparison(expression) {
|
||||
return (
|
||||
expression.type === "LogicalExpression" &&
|
||||
expression.operator === "||" &&
|
||||
expression.left.type === "BinaryExpression" &&
|
||||
expression.left.operator === "===" &&
|
||||
expression.right.type === "BinaryExpression" &&
|
||||
expression.right.operator === "==="
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff the expression checks for undefined and null.
|
||||
* Example: value === null || value === undefined
|
||||
* @param {ASTNode} expression Test condition
|
||||
* @param {import('eslint-scope').Scope} scope Scope of the expression
|
||||
* @returns {boolean} True iff explicit nullish comparison
|
||||
*/
|
||||
function isExplicitNullishComparison(expression, scope) {
|
||||
if (!isDoubleComparison(expression)) {
|
||||
return false;
|
||||
}
|
||||
const leftReference = isReference(expression.left.left) ? "left" : "right";
|
||||
const leftNullish = leftReference === "left" ? "right" : "left";
|
||||
const rightReference = isReference(expression.right.left)
|
||||
? "left"
|
||||
: "right";
|
||||
const rightNullish = rightReference === "left" ? "right" : "left";
|
||||
|
||||
return (
|
||||
astUtils.isSameReference(
|
||||
expression.left[leftReference],
|
||||
expression.right[rightReference],
|
||||
) &&
|
||||
((astUtils.isNullLiteral(expression.left[leftNullish]) &&
|
||||
isUndefined(expression.right[rightNullish], scope)) ||
|
||||
(isUndefined(expression.left[leftNullish], scope) &&
|
||||
astUtils.isNullLiteral(expression.right[rightNullish])))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true for Boolean(arg) calls
|
||||
* @param {ASTNode} expression Test condition
|
||||
* @param {import('eslint-scope').Scope} scope Scope of the expression
|
||||
* @returns {boolean} Whether the expression is a boolean cast
|
||||
*/
|
||||
function isBooleanCast(expression, scope) {
|
||||
return (
|
||||
expression.type === "CallExpression" &&
|
||||
expression.callee.name === "Boolean" &&
|
||||
expression.arguments.length === 1 &&
|
||||
astUtils.isReferenceToGlobalVariable(scope, expression.callee)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true for:
|
||||
* truthiness checks: value, Boolean(value), !!value
|
||||
* falsiness checks: !value, !Boolean(value)
|
||||
* nullish checks: value == null, value === undefined || value === null
|
||||
* @param {ASTNode} expression Test condition
|
||||
* @param {import('eslint-scope').Scope} scope Scope of the expression
|
||||
* @returns {?{ reference: ASTNode, operator: '??'|'||'|'&&'}} Null if not a known existence
|
||||
*/
|
||||
function getExistence(expression, scope) {
|
||||
const isNegated =
|
||||
expression.type === "UnaryExpression" && expression.operator === "!";
|
||||
const base = isNegated ? expression.argument : expression;
|
||||
|
||||
switch (true) {
|
||||
case isReference(base):
|
||||
return { reference: base, operator: isNegated ? "||" : "&&" };
|
||||
case base.type === "UnaryExpression" &&
|
||||
base.operator === "!" &&
|
||||
isReference(base.argument):
|
||||
return { reference: base.argument, operator: "&&" };
|
||||
case isBooleanCast(base, scope) && isReference(base.arguments[0]):
|
||||
return {
|
||||
reference: base.arguments[0],
|
||||
operator: isNegated ? "||" : "&&",
|
||||
};
|
||||
case isImplicitNullishComparison(expression, scope):
|
||||
return {
|
||||
reference: isReference(expression.left)
|
||||
? expression.left
|
||||
: expression.right,
|
||||
operator: "??",
|
||||
};
|
||||
case isExplicitNullishComparison(expression, scope):
|
||||
return {
|
||||
reference: isReference(expression.left.left)
|
||||
? expression.left.left
|
||||
: expression.left.right,
|
||||
operator: "??",
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff the node is inside a with block
|
||||
* @param {ASTNode} node Node to check
|
||||
* @returns {boolean} True iff passed node is inside a with block
|
||||
*/
|
||||
function isInsideWithBlock(node) {
|
||||
if (node.type === "Program") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return node.parent.type === "WithStatement" && node.parent.body === node
|
||||
? true
|
||||
: isInsideWithBlock(node.parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the leftmost operand of a consecutive logical expression.
|
||||
* @param {SourceCode} sourceCode The ESLint source code object
|
||||
* @param {LogicalExpression} node LogicalExpression
|
||||
* @returns {Expression} Leftmost operand
|
||||
*/
|
||||
function getLeftmostOperand(sourceCode, node) {
|
||||
let left = node.left;
|
||||
|
||||
while (
|
||||
left.type === "LogicalExpression" &&
|
||||
left.operator === node.operator
|
||||
) {
|
||||
if (astUtils.isParenthesised(sourceCode, left)) {
|
||||
/*
|
||||
* It should have associativity,
|
||||
* but ignore it if use parentheses to make the evaluation order clear.
|
||||
*/
|
||||
return left;
|
||||
}
|
||||
left = left.left;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Require or disallow logical assignment operator shorthand",
|
||||
recommended: false,
|
||||
frozen: true,
|
||||
url: "https://eslint.org/docs/latest/rules/logical-assignment-operators",
|
||||
},
|
||||
|
||||
schema: {
|
||||
type: "array",
|
||||
oneOf: [
|
||||
{
|
||||
items: [
|
||||
{ const: "always" },
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
enforceForIfStatements: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
minItems: 0, // 0 for allowing passing no options
|
||||
maxItems: 2,
|
||||
},
|
||||
{
|
||||
items: [{ const: "never" }],
|
||||
minItems: 1,
|
||||
maxItems: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
defaultOptions: ["always"],
|
||||
|
||||
fixable: "code",
|
||||
hasSuggestions: true,
|
||||
messages: {
|
||||
assignment:
|
||||
"Assignment (=) can be replaced with operator assignment ({{operator}}).",
|
||||
useLogicalOperator:
|
||||
"Convert this assignment to use the operator {{ operator }}.",
|
||||
logical:
|
||||
"Logical expression can be replaced with an assignment ({{ operator }}).",
|
||||
convertLogical:
|
||||
"Replace this logical expression with an assignment with the operator {{ operator }}.",
|
||||
if: "'if' statement can be replaced with a logical operator assignment with operator {{ operator }}.",
|
||||
convertIf:
|
||||
"Replace this 'if' statement with a logical assignment with operator {{ operator }}.",
|
||||
unexpected:
|
||||
"Unexpected logical operator assignment ({{operator}}) shorthand.",
|
||||
separate:
|
||||
"Separate the logical assignment into an assignment with a logical operator.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const mode = context.options[0];
|
||||
const checkIf =
|
||||
mode === "always" &&
|
||||
context.options.length > 1 &&
|
||||
context.options[1].enforceForIfStatements;
|
||||
const sourceCode = context.sourceCode;
|
||||
const isStrict = sourceCode.getScope(sourceCode.ast).isStrict;
|
||||
|
||||
/**
|
||||
* Returns false if the access could be a getter
|
||||
* @param {ASTNode} node Assignment expression
|
||||
* @returns {boolean} True iff the fix is safe
|
||||
*/
|
||||
function cannotBeGetter(node) {
|
||||
return (
|
||||
node.type === "Identifier" &&
|
||||
(isStrict || !isInsideWithBlock(node))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether only a single property is accessed
|
||||
* @param {ASTNode} node reference
|
||||
* @returns {boolean} True iff a single property is accessed
|
||||
*/
|
||||
function accessesSingleProperty(node) {
|
||||
if (!isStrict && isInsideWithBlock(node)) {
|
||||
return node.type === "Identifier";
|
||||
}
|
||||
|
||||
return (
|
||||
node.type === "MemberExpression" &&
|
||||
baseTypes.has(node.object.type) &&
|
||||
(!node.computed ||
|
||||
(node.property.type !== "MemberExpression" &&
|
||||
node.property.type !== "ChainExpression"))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a fixer or suggestion whether on the fix is safe.
|
||||
* @param {{ messageId: string, node: ASTNode }} descriptor Report descriptor without fix or suggest
|
||||
* @param {{ messageId: string, fix: Function }} suggestion Adds the fix or the whole suggestion as only element in "suggest" to suggestion
|
||||
* @param {boolean} shouldBeFixed Fix iff the condition is true
|
||||
* @returns {Object} Descriptor with either an added fix or suggestion
|
||||
*/
|
||||
function createConditionalFixer(descriptor, suggestion, shouldBeFixed) {
|
||||
if (shouldBeFixed) {
|
||||
return {
|
||||
...descriptor,
|
||||
fix: suggestion.fix,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...descriptor,
|
||||
suggest: [suggestion],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the operator token for assignments and binary expressions
|
||||
* @param {ASTNode} node AssignmentExpression or BinaryExpression
|
||||
* @returns {import('eslint').AST.Token} Operator token between the left and right expression
|
||||
*/
|
||||
function getOperatorToken(node) {
|
||||
return sourceCode.getFirstTokenBetween(
|
||||
node.left,
|
||||
node.right,
|
||||
token => token.value === node.operator,
|
||||
);
|
||||
}
|
||||
|
||||
if (mode === "never") {
|
||||
return {
|
||||
// foo ||= bar
|
||||
AssignmentExpression(assignment) {
|
||||
if (
|
||||
!astUtils.isLogicalAssignmentOperator(
|
||||
assignment.operator,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const descriptor = {
|
||||
messageId: "unexpected",
|
||||
node: assignment,
|
||||
data: { operator: assignment.operator },
|
||||
};
|
||||
const suggestion = {
|
||||
messageId: "separate",
|
||||
*fix(ruleFixer) {
|
||||
if (
|
||||
sourceCode.getCommentsInside(assignment)
|
||||
.length > 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const operatorToken = getOperatorToken(assignment);
|
||||
|
||||
// -> foo = bar
|
||||
yield ruleFixer.replaceText(operatorToken, "=");
|
||||
|
||||
const assignmentText = sourceCode.getText(
|
||||
assignment.left,
|
||||
);
|
||||
const operator = assignment.operator.slice(0, -1);
|
||||
|
||||
// -> foo = foo || bar
|
||||
yield ruleFixer.insertTextAfter(
|
||||
operatorToken,
|
||||
` ${assignmentText} ${operator}`,
|
||||
);
|
||||
|
||||
const precedence =
|
||||
astUtils.getPrecedence(assignment.right) <=
|
||||
astUtils.getPrecedence({
|
||||
type: "LogicalExpression",
|
||||
operator,
|
||||
});
|
||||
|
||||
// ?? and || / && cannot be mixed but have same precedence
|
||||
const mixed =
|
||||
assignment.operator === "??=" &&
|
||||
astUtils.isLogicalExpression(assignment.right);
|
||||
|
||||
if (
|
||||
!astUtils.isParenthesised(
|
||||
sourceCode,
|
||||
assignment.right,
|
||||
) &&
|
||||
(precedence || mixed)
|
||||
) {
|
||||
// -> foo = foo || (bar)
|
||||
yield ruleFixer.insertTextBefore(
|
||||
assignment.right,
|
||||
"(",
|
||||
);
|
||||
yield ruleFixer.insertTextAfter(
|
||||
assignment.right,
|
||||
")",
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
context.report(
|
||||
createConditionalFixer(
|
||||
descriptor,
|
||||
suggestion,
|
||||
cannotBeGetter(assignment.left),
|
||||
),
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
// foo = foo || bar
|
||||
"AssignmentExpression[operator='='][right.type='LogicalExpression']"(
|
||||
assignment,
|
||||
) {
|
||||
const leftOperand = getLeftmostOperand(
|
||||
sourceCode,
|
||||
assignment.right,
|
||||
);
|
||||
|
||||
if (!astUtils.isSameReference(assignment.left, leftOperand)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const descriptor = {
|
||||
messageId: "assignment",
|
||||
node: assignment,
|
||||
data: { operator: `${assignment.right.operator}=` },
|
||||
};
|
||||
const suggestion = {
|
||||
messageId: "useLogicalOperator",
|
||||
data: { operator: `${assignment.right.operator}=` },
|
||||
*fix(ruleFixer) {
|
||||
if (
|
||||
sourceCode.getCommentsInside(assignment).length > 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No need for parenthesis around the assignment based on precedence as the precedence stays the same even with changed operator
|
||||
const assignmentOperatorToken =
|
||||
getOperatorToken(assignment);
|
||||
|
||||
// -> foo ||= foo || bar
|
||||
yield ruleFixer.insertTextBefore(
|
||||
assignmentOperatorToken,
|
||||
assignment.right.operator,
|
||||
);
|
||||
|
||||
// -> foo ||= bar
|
||||
const logicalOperatorToken = getOperatorToken(
|
||||
leftOperand.parent,
|
||||
);
|
||||
const firstRightOperandToken =
|
||||
sourceCode.getTokenAfter(logicalOperatorToken);
|
||||
|
||||
yield ruleFixer.removeRange([
|
||||
leftOperand.parent.range[0],
|
||||
firstRightOperandToken.range[0],
|
||||
]);
|
||||
},
|
||||
};
|
||||
|
||||
context.report(
|
||||
createConditionalFixer(
|
||||
descriptor,
|
||||
suggestion,
|
||||
cannotBeGetter(assignment.left),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
// foo || (foo = bar)
|
||||
'LogicalExpression[right.type="AssignmentExpression"][right.operator="="]'(
|
||||
logical,
|
||||
) {
|
||||
// Right side has to be parenthesized, otherwise would be parsed as (foo || foo) = bar which is illegal
|
||||
if (
|
||||
isReference(logical.left) &&
|
||||
astUtils.isSameReference(logical.left, logical.right.left)
|
||||
) {
|
||||
const descriptor = {
|
||||
messageId: "logical",
|
||||
node: logical,
|
||||
data: { operator: `${logical.operator}=` },
|
||||
};
|
||||
const suggestion = {
|
||||
messageId: "convertLogical",
|
||||
data: { operator: `${logical.operator}=` },
|
||||
*fix(ruleFixer) {
|
||||
if (
|
||||
sourceCode.getCommentsInside(logical).length > 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parentPrecedence = astUtils.getPrecedence(
|
||||
logical.parent,
|
||||
);
|
||||
const requiresOuterParenthesis =
|
||||
logical.parent.type !== "ExpressionStatement" &&
|
||||
(parentPrecedence === -1 ||
|
||||
astUtils.getPrecedence({
|
||||
type: "AssignmentExpression",
|
||||
}) < parentPrecedence);
|
||||
|
||||
if (
|
||||
!astUtils.isParenthesised(
|
||||
sourceCode,
|
||||
logical,
|
||||
) &&
|
||||
requiresOuterParenthesis
|
||||
) {
|
||||
yield ruleFixer.insertTextBefore(logical, "(");
|
||||
yield ruleFixer.insertTextAfter(logical, ")");
|
||||
}
|
||||
|
||||
// Also removes all opening parenthesis
|
||||
yield ruleFixer.removeRange([
|
||||
logical.range[0],
|
||||
logical.right.range[0],
|
||||
]); // -> foo = bar)
|
||||
|
||||
// Also removes all ending parenthesis
|
||||
yield ruleFixer.removeRange([
|
||||
logical.right.range[1],
|
||||
logical.range[1],
|
||||
]); // -> foo = bar
|
||||
|
||||
const operatorToken = getOperatorToken(
|
||||
logical.right,
|
||||
);
|
||||
|
||||
yield ruleFixer.insertTextBefore(
|
||||
operatorToken,
|
||||
logical.operator,
|
||||
); // -> foo ||= bar
|
||||
},
|
||||
};
|
||||
const fix =
|
||||
cannotBeGetter(logical.left) ||
|
||||
accessesSingleProperty(logical.left);
|
||||
|
||||
context.report(
|
||||
createConditionalFixer(descriptor, suggestion, fix),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// if (foo) foo = bar
|
||||
"IfStatement[alternate=null]"(ifNode) {
|
||||
if (!checkIf) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasBody = ifNode.consequent.type === "BlockStatement";
|
||||
|
||||
if (hasBody && ifNode.consequent.body.length !== 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const body = hasBody
|
||||
? ifNode.consequent.body[0]
|
||||
: ifNode.consequent;
|
||||
const scope = sourceCode.getScope(ifNode);
|
||||
const existence = getExistence(ifNode.test, scope);
|
||||
|
||||
if (
|
||||
body.type === "ExpressionStatement" &&
|
||||
body.expression.type === "AssignmentExpression" &&
|
||||
body.expression.operator === "=" &&
|
||||
existence !== null &&
|
||||
astUtils.isSameReference(
|
||||
existence.reference,
|
||||
body.expression.left,
|
||||
)
|
||||
) {
|
||||
const descriptor = {
|
||||
messageId: "if",
|
||||
node: ifNode,
|
||||
data: { operator: `${existence.operator}=` },
|
||||
};
|
||||
const suggestion = {
|
||||
messageId: "convertIf",
|
||||
data: { operator: `${existence.operator}=` },
|
||||
*fix(ruleFixer) {
|
||||
if (
|
||||
sourceCode.getCommentsInside(ifNode).length > 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstBodyToken =
|
||||
sourceCode.getFirstToken(body);
|
||||
const prevToken = sourceCode.getTokenBefore(ifNode);
|
||||
|
||||
if (
|
||||
prevToken !== null &&
|
||||
prevToken.value !== ";" &&
|
||||
prevToken.value !== "{" &&
|
||||
firstBodyToken.type !== "Identifier" &&
|
||||
firstBodyToken.type !== "Keyword"
|
||||
) {
|
||||
// Do not fix if the fixed statement could be part of the previous statement (eg. fn() if (a == null) (a) = b --> fn()(a) ??= b)
|
||||
return;
|
||||
}
|
||||
|
||||
const operatorToken = getOperatorToken(
|
||||
body.expression,
|
||||
);
|
||||
|
||||
yield ruleFixer.insertTextBefore(
|
||||
operatorToken,
|
||||
existence.operator,
|
||||
); // -> if (foo) foo ||= bar
|
||||
|
||||
yield ruleFixer.removeRange([
|
||||
ifNode.range[0],
|
||||
body.range[0],
|
||||
]); // -> foo ||= bar
|
||||
|
||||
yield ruleFixer.removeRange([
|
||||
body.range[1],
|
||||
ifNode.range[1],
|
||||
]); // -> foo ||= bar, only present if "if" had a body
|
||||
|
||||
const nextToken = sourceCode.getTokenAfter(
|
||||
body.expression,
|
||||
);
|
||||
|
||||
if (
|
||||
hasBody &&
|
||||
nextToken !== null &&
|
||||
nextToken.value !== ";"
|
||||
) {
|
||||
yield ruleFixer.insertTextAfter(ifNode, ";");
|
||||
}
|
||||
},
|
||||
};
|
||||
const shouldBeFixed =
|
||||
cannotBeGetter(existence.reference) ||
|
||||
(ifNode.test.type !== "LogicalExpression" &&
|
||||
accessesSingleProperty(existence.reference));
|
||||
|
||||
context.report(
|
||||
createConditionalFixer(
|
||||
descriptor,
|
||||
suggestion,
|
||||
shouldBeFixed,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2022_intl = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2022_intl = {
|
||||
libs: [],
|
||||
variables: [['Intl', base_config_1.TYPE_VALUE]],
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { TSESTree } from '@typescript-eslint/types';
|
||||
export declare const getKeys: (node: TSESTree.Node) => readonly string[];
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @fileoverview Common utils for AST.
|
||||
*
|
||||
* This file contains only shared items for core and rules.
|
||||
* If you make a utility for rules, please see `../rules/utils/ast-utils.js`.
|
||||
*
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const breakableTypePattern =
|
||||
/^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/u;
|
||||
const lineBreakPattern = /\r\n|[\r\n\u2028\u2029]/u;
|
||||
const shebangPattern = /^#!([^\r\n]+)/u;
|
||||
|
||||
/**
|
||||
* Creates a version of the `lineBreakPattern` regex with the global flag.
|
||||
* Global regexes are mutable, so this needs to be a function instead of a constant.
|
||||
* @returns {RegExp} A global regular expression that matches line terminators
|
||||
*/
|
||||
function createGlobalLinebreakMatcher() {
|
||||
return new RegExp(lineBreakPattern.source, "gu");
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
breakableTypePattern,
|
||||
lineBreakPattern,
|
||||
createGlobalLinebreakMatcher,
|
||||
shebangPattern,
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @fileoverview Disallow the use of process.env()
|
||||
* @author Vignesh Anand
|
||||
* @deprecated in ESLint v7.0.0
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: {
|
||||
message: "Node.js rules were moved out of ESLint core.",
|
||||
url: "https://eslint.org/docs/latest/use/migrating-to-7.0.0#deprecate-node-rules",
|
||||
deprecatedSince: "7.0.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
message:
|
||||
"eslint-plugin-n now maintains deprecated Node.js-related rules.",
|
||||
plugin: {
|
||||
name: "eslint-plugin-n",
|
||||
url: "https://github.com/eslint-community/eslint-plugin-n",
|
||||
},
|
||||
rule: {
|
||||
name: "no-process-env",
|
||||
url: "https://github.com/eslint-community/eslint-plugin-n/tree/master/docs/rules/no-process-env.md",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "Disallow the use of `process.env`",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-process-env",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
unexpectedProcessEnv: "Unexpected use of process.env.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
return {
|
||||
MemberExpression(node) {
|
||||
const objectName = node.object.name,
|
||||
propertyName = node.property.name;
|
||||
|
||||
if (
|
||||
objectName === "process" &&
|
||||
!node.computed &&
|
||||
propertyName &&
|
||||
propertyName === "env"
|
||||
) {
|
||||
context.report({ node, messageId: "unexpectedProcessEnv" });
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
function _inherits_loose(subClass, superClass) {
|
||||
subClass.prototype = Object.create(superClass.prototype);
|
||||
subClass.prototype.constructor = subClass;
|
||||
subClass.__proto__ = superClass;
|
||||
}
|
||||
export { _inherits_loose as _ };
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"hmac.js","sourceRoot":"","sources":["../src/hmac.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAA0B,MAAM,YAAY,CAAC;AAElG,MAAM,OAAO,IAAwB,SAAQ,IAAa;IAQxD,YAAY,IAAW,EAAE,IAAW;QAClC,KAAK,EAAE,CAAC;QAJF,aAAQ,GAAG,KAAK,CAAC;QACjB,cAAS,GAAG,KAAK,CAAC;QAIxB,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,EAAO,CAAC;QAChC,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,UAAU;YACzC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrC,wCAAwC;QACxC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC1E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,mHAAmH;QACnH,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,EAAO,CAAC;QAChC,uCAAuC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC;QAC3D,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,KAAK,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;IACD,MAAM,CAAC,GAAU;QACf,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,UAAU,CAAC,GAAe;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IACD,MAAM;QACJ,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACrB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,UAAU,CAAC,EAAY;QACrB,mGAAmG;QACnG,EAAE,KAAF,EAAE,GAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAC;QACtD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QACxE,EAAE,GAAG,EAAU,CAAC;QAChB,EAAE,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACvB,EAAE,CAAC,SAAS,GAAG,SAAS,CAAC;QACzB,EAAE,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACvB,EAAE,CAAC,SAAS,GAAG,SAAS,CAAC;QACzB,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACtC,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,KAAK;QACH,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO;QACL,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,IAAI,GAGb,CAAC,IAAW,EAAE,GAAU,EAAE,OAAc,EAAc,EAAE,CAC1D,IAAI,IAAI,CAAM,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AACpD,IAAI,CAAC,MAAM,GAAG,CAAC,IAAW,EAAE,GAAU,EAAE,EAAE,CAAC,IAAI,IAAI,CAAM,IAAI,EAAE,GAAG,CAAC,CAAC"}
|
||||
@@ -0,0 +1,243 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("globalRegistry", () => {
|
||||
const reg = z.registry();
|
||||
|
||||
const a = z.string();
|
||||
reg.add(a);
|
||||
expect(reg.has(a)).toEqual(true);
|
||||
|
||||
reg.remove(a);
|
||||
expect(reg.has(a)).toEqual(false);
|
||||
|
||||
a.register(z.globalRegistry, { field: "sup" });
|
||||
expect(z.globalRegistry.has(a)).toEqual(true);
|
||||
expect(z.globalRegistry.get(a)).toEqual({ field: "sup" });
|
||||
|
||||
z.globalRegistry.remove(a);
|
||||
expect(z.globalRegistry.has(a)).toEqual(false);
|
||||
});
|
||||
|
||||
test("globalRegistry is singleton and attached to globalThis", () => {
|
||||
expect(z.globalRegistry).toBe((globalThis as any).__zod_globalRegistry);
|
||||
});
|
||||
|
||||
test("z.registry", () => {
|
||||
const fieldRegistry = z.registry<{ name: string; description: string }>();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a, { name: "hello", description: "world" });
|
||||
const a_meta = fieldRegistry.get(a);
|
||||
expect(a_meta).toEqual({ name: "hello", description: "world" });
|
||||
|
||||
fieldRegistry.remove(a);
|
||||
expect(fieldRegistry.has(a)).toEqual(false);
|
||||
expect(fieldRegistry.get(a)).toEqual(undefined);
|
||||
});
|
||||
|
||||
test("z.registry no metadata", () => {
|
||||
const fieldRegistry = z.registry();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a);
|
||||
fieldRegistry.add(z.number());
|
||||
expect(fieldRegistry.get(a)).toEqual(undefined);
|
||||
expect(fieldRegistry.has(a)).toEqual(true);
|
||||
});
|
||||
|
||||
test("z.registry with schema constraints", () => {
|
||||
const fieldRegistry = z.registry<{ name: string; description: string }, z.ZodString>();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a, { name: "hello", description: "world" });
|
||||
// @ts-expect-error
|
||||
fieldRegistry.add(z.number(), { name: "test" });
|
||||
// @ts-expect-error
|
||||
z.number().register(fieldRegistry, { name: "test", description: "test" });
|
||||
});
|
||||
|
||||
// test("z.namedRegistry", () => {
|
||||
// const namedReg = z
|
||||
// .namedRegistry<{ name: string; description: string }>()
|
||||
// .add(z.string(), { name: "hello", description: "world" })
|
||||
// .add(z.number(), { name: "number", description: "number" });
|
||||
|
||||
// expect(namedReg.get("hello")).toEqual({
|
||||
// name: "hello",
|
||||
// description: "world",
|
||||
// });
|
||||
// expect(namedReg.has("hello")).toEqual(true);
|
||||
// expect(namedReg.get("number")).toEqual({
|
||||
// name: "number",
|
||||
// description: "number",
|
||||
// });
|
||||
|
||||
// // @ts-expect-error
|
||||
// namedReg.get("world");
|
||||
// // @ts-expect-error
|
||||
// expect(namedReg.get("world")).toEqual(undefined);
|
||||
|
||||
// const hello = namedReg.get("hello");
|
||||
// expect(hello).toEqual({ name: "hello", description: "world" });
|
||||
// expectTypeOf<typeof hello>().toEqualTypeOf<{
|
||||
// name: "hello";
|
||||
// description: "world";
|
||||
// }>();
|
||||
// expectTypeOf<typeof namedReg.items>().toEqualTypeOf<{
|
||||
// hello: { name: "hello"; description: "world" };
|
||||
// number: { name: "number"; description: "number" };
|
||||
// }>();
|
||||
// });
|
||||
|
||||
test("output type in registry meta", () => {
|
||||
const reg = z.registry<{ out: z.$output }>();
|
||||
const a = z.string();
|
||||
reg.add(a, { out: "asdf" });
|
||||
// @ts-expect-error
|
||||
reg.add(a, 1234);
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ out: string } | undefined>();
|
||||
});
|
||||
|
||||
test("output type in registry meta - objects and arrays", () => {
|
||||
const reg = z.registry<{ name: string; examples: z.$output[] }>();
|
||||
const a = z.string();
|
||||
reg.add(a, { name: "hello", examples: ["world"] });
|
||||
|
||||
// @ts-expect-error
|
||||
reg.add(a, { name: "hello", examples: "world" });
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ name: string; examples: string[] } | undefined>();
|
||||
});
|
||||
|
||||
test("input type in registry meta", () => {
|
||||
const reg = z.registry<{ in: z.$input }>();
|
||||
const a = z.pipe(z.number(), z.transform(String));
|
||||
reg.add(a, { in: 1234 });
|
||||
// @ts-expect-error
|
||||
reg.add(a, "1234");
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ in: number } | undefined>();
|
||||
});
|
||||
|
||||
test("input type in registry meta - objects and arrays", () => {
|
||||
const reg = z.registry<{ name: string; examples: z.$input[] }>();
|
||||
const a = z.pipe(z.number(), z.transform(String));
|
||||
reg.add(a, { name: "hello", examples: [1234] });
|
||||
|
||||
// @ts-expect-error
|
||||
reg.add(a, { name: "hello", examples: "world" });
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ name: string; examples: number[] } | undefined>();
|
||||
});
|
||||
|
||||
test(".meta method", () => {
|
||||
const a1 = z.string();
|
||||
const a2 = a1.meta({ name: "hello" });
|
||||
|
||||
expect(a1.meta()).toEqual(undefined);
|
||||
expect(a2.meta()).toEqual({ name: "hello" });
|
||||
expect(a1 === a2).toEqual(false);
|
||||
});
|
||||
|
||||
test(".meta metadata does not bubble up", () => {
|
||||
const a1 = z.string().meta({ name: "hello" });
|
||||
const a2 = a1.optional();
|
||||
|
||||
expect(a1.meta()).toEqual({ name: "hello" });
|
||||
expect(a2.meta()).toEqual(undefined);
|
||||
});
|
||||
|
||||
test(".describe", () => {
|
||||
const a1 = z.string();
|
||||
const a2 = a1.describe("Hello");
|
||||
|
||||
expect(a1.description).toEqual(undefined);
|
||||
expect(a2.description).toEqual("Hello");
|
||||
});
|
||||
|
||||
test("inherit across clone", () => {
|
||||
const A = z.string().meta({ a: true });
|
||||
expect(A.meta()).toEqual({ a: true });
|
||||
const B = A.meta({ b: true });
|
||||
expect(B.meta()).toEqual({ a: true, b: true });
|
||||
const C = B.describe("hello");
|
||||
expect(C.meta()).toEqual({ a: true, b: true, description: "hello" });
|
||||
});
|
||||
|
||||
test("loose examples", () => {
|
||||
z.string().register(z.globalRegistry, {
|
||||
examples: ["example"],
|
||||
});
|
||||
});
|
||||
|
||||
test("function meta without replacement", () => {
|
||||
const myReg = z.registry<{
|
||||
defaulter: (arg: string, test: boolean) => number;
|
||||
}>();
|
||||
|
||||
const mySchema = z.date();
|
||||
myReg.add(mySchema, {
|
||||
defaulter: (arg, _test) => {
|
||||
return arg.length;
|
||||
},
|
||||
});
|
||||
|
||||
expect(myReg.get(mySchema)!.defaulter("hello", true)).toEqual(5);
|
||||
});
|
||||
|
||||
test("function meta with replacement", () => {
|
||||
const myReg = z.registry<{
|
||||
defaulter: (arg: z.$input, test: boolean) => z.$output;
|
||||
}>();
|
||||
|
||||
const mySchema = z.string().transform((val) => val.length);
|
||||
myReg.add(mySchema, {
|
||||
defaulter: (arg, _test) => {
|
||||
return arg.length;
|
||||
},
|
||||
});
|
||||
|
||||
expect(myReg.get(mySchema)!.defaulter("hello", true)).toEqual(5);
|
||||
});
|
||||
|
||||
test("test .clear()", () => {
|
||||
const reg = z.registry();
|
||||
const a = z.string();
|
||||
reg.add(a);
|
||||
expect(reg.has(a)).toEqual(true);
|
||||
reg.clear();
|
||||
expect(reg.has(a)).toEqual(false);
|
||||
});
|
||||
|
||||
test("re-registering same id silently overwrites", () => {
|
||||
const reg = z.registry<z.core.GlobalMeta>();
|
||||
const a = z.string();
|
||||
const b = z.number();
|
||||
|
||||
reg.add(a, { id: "shared-id" });
|
||||
reg.add(b, { id: "shared-id" });
|
||||
|
||||
// No error thrown, b now owns the id
|
||||
expect(reg._idmap.get("shared-id")).toBe(b);
|
||||
});
|
||||
|
||||
test("toJSONSchema throws on duplicate id across different schemas", () => {
|
||||
const reg = z.registry<z.core.GlobalMeta>();
|
||||
const a = z.string().register(reg, { id: "duplicate-id" });
|
||||
const b = z.number().register(reg, { id: "duplicate-id" });
|
||||
|
||||
const wrapper = z.object({ a, b });
|
||||
|
||||
expect(() => z.toJSONSchema(wrapper, { metadata: reg })).toThrow(
|
||||
'Duplicate schema id "duplicate-id" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.'
|
||||
);
|
||||
});
|
||||
|
||||
test("toJSONSchema allows same schema with same id", () => {
|
||||
const reg = z.registry<z.core.GlobalMeta>();
|
||||
const shared = z.string().register(reg, { id: "shared-id" });
|
||||
|
||||
const wrapper = z.object({ a: shared, b: shared });
|
||||
|
||||
// Should not throw - same schema instance used twice
|
||||
const result = z.toJSONSchema(wrapper, { metadata: reg });
|
||||
expect(result.$defs?.["shared-id"]).toBeDefined();
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Returns the element within root under the path given by pathSegments.
|
||||
* @param {Object} root
|
||||
* @param {string[]} pathSegments
|
||||
* @param {boolean} [appendIfMissing=false] - all objects are created if they do not exist
|
||||
* @returns {Object} - the object under the path. If appendIsMissing is false and the path does not exist, returns null
|
||||
*/
|
||||
module.exports.getObject = function getObject(root, pathSegments, appendIfMissing) {
|
||||
var target = root;
|
||||
var pathSeg;
|
||||
var i;
|
||||
for (i = 0; i < pathSegments.length; i++) {
|
||||
pathSeg = pathSegments[i];
|
||||
if (!target.hasOwnProperty(pathSeg)) {
|
||||
if (appendIfMissing) {
|
||||
target[pathSeg] = {};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
target = target[pathSeg];
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes the object to the path in root. Overwrites if an object exists.
|
||||
* Note: root is edited in place!
|
||||
* @param {Object} root
|
||||
* @param {string[]} pathSegments
|
||||
* @param {Object} obj
|
||||
*/
|
||||
module.exports.setObject = function setObject(root, pathSegments, obj) {
|
||||
var target = root;
|
||||
var pathSeg;
|
||||
var i;
|
||||
var max = pathSegments.length;
|
||||
for (i = 0; i < max; i++) {
|
||||
pathSeg = pathSegments[i];
|
||||
if (i === max - 1) {
|
||||
target[pathSeg] = obj;
|
||||
} else if (!target.hasOwnProperty(pathSeg)) {
|
||||
target[pathSeg] = {};
|
||||
}
|
||||
target = target[pathSeg];
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Parser, Printer } from "../index.js";
|
||||
|
||||
export declare const parsers: {
|
||||
glimmer: Parser;
|
||||
};
|
||||
|
||||
export declare const printers: {
|
||||
glimmer: Printer;
|
||||
};
|
||||
@@ -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: "حرف", verb: "أن يحوي" },
|
||||
file: { unit: "بايت", verb: "أن يحوي" },
|
||||
array: { unit: "عنصر", verb: "أن يحوي" },
|
||||
set: { unit: "عنصر", verb: "أن يحوي" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const FormatDictionary: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "مدخل",
|
||||
email: "بريد إلكتروني",
|
||||
url: "رابط",
|
||||
emoji: "إيموجي",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "تاريخ ووقت بمعيار ISO",
|
||||
date: "تاريخ بمعيار ISO",
|
||||
time: "وقت بمعيار ISO",
|
||||
duration: "مدة بمعيار ISO",
|
||||
ipv4: "عنوان IPv4",
|
||||
ipv6: "عنوان IPv6",
|
||||
cidrv4: "مدى عناوين بصيغة IPv4",
|
||||
cidrv6: "مدى عناوين بصيغة IPv6",
|
||||
base64: "نَص بترميز base64-encoded",
|
||||
base64url: "نَص بترميز base64url-encoded",
|
||||
json_string: "نَص على هيئة JSON",
|
||||
e164: "رقم هاتف بمعيار E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "مدخل",
|
||||
};
|
||||
|
||||
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 `مدخلات غير مقبولة: يفترض إدخال instanceof ${issue.expected}، ولكن تم إدخال ${received}`;
|
||||
}
|
||||
return `مدخلات غير مقبولة: يفترض إدخال ${expected}، ولكن تم إدخال ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `مدخلات غير مقبولة: يفترض إدخال ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `اختيار غير مقبول: يتوقع انتقاء أحد هذه الخيارات: ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return ` أكبر من اللازم: يفترض أن تكون ${issue.origin ?? "القيمة"} ${adj} ${issue.maximum.toString()} ${sizing.unit ?? "عنصر"}`;
|
||||
return `أكبر من اللازم: يفترض أن تكون ${issue.origin ?? "القيمة"} ${adj} ${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `أصغر من اللازم: يفترض لـ ${issue.origin} أن يكون ${adj} ${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `أصغر من اللازم: يفترض لـ ${issue.origin} أن يكون ${adj} ${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `نَص غير مقبول: يجب أن يبدأ بـ "${issue.prefix}"`;
|
||||
if (_issue.format === "ends_with") return `نَص غير مقبول: يجب أن ينتهي بـ "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `نَص غير مقبول: يجب أن يتضمَّن "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `نَص غير مقبول: يجب أن يطابق النمط ${_issue.pattern}`;
|
||||
return `${FormatDictionary[_issue.format] ?? issue.format} غير مقبول`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `رقم غير مقبول: يجب أن يكون من مضاعفات ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `معرف${issue.keys.length > 1 ? "ات" : ""} غريب${issue.keys.length > 1 ? "ة" : ""}: ${util.joinValues(issue.keys, "، ")}`;
|
||||
case "invalid_key":
|
||||
return `معرف غير مقبول في ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "مدخل غير مقبول";
|
||||
case "invalid_element":
|
||||
return `مدخل غير مقبول في ${issue.origin}`;
|
||||
default:
|
||||
return "مدخل غير مقبول";
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user