WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('node:fs')
|
||||
const { once } = require('node:events')
|
||||
|
||||
async function run (opts) {
|
||||
if (!opts.destination) throw new Error('kaboom')
|
||||
const stream = fs.createWriteStream(opts.destination)
|
||||
await once(stream, 'open')
|
||||
return stream
|
||||
}
|
||||
|
||||
module.exports = run
|
||||
@@ -0,0 +1,427 @@
|
||||
'use strict'
|
||||
|
||||
/* eslint no-prototype-builtins: 0 */
|
||||
|
||||
const diagChan = require('node:diagnostics_channel')
|
||||
const format = require('quick-format-unescaped')
|
||||
const { mapHttpRequest, mapHttpResponse } = require('pino-std-serializers')
|
||||
const SonicBoom = require('sonic-boom')
|
||||
const onExit = require('on-exit-leak-free')
|
||||
const {
|
||||
lsCacheSym,
|
||||
chindingsSym,
|
||||
writeSym,
|
||||
serializersSym,
|
||||
formatOptsSym,
|
||||
endSym,
|
||||
stringifiersSym,
|
||||
stringifySym,
|
||||
stringifySafeSym,
|
||||
wildcardFirstSym,
|
||||
nestedKeySym,
|
||||
formattersSym,
|
||||
messageKeySym,
|
||||
errorKeySym,
|
||||
nestedKeyStrSym,
|
||||
msgPrefixSym
|
||||
} = require('./symbols')
|
||||
const { isMainThread } = require('worker_threads')
|
||||
const transport = require('./transport')
|
||||
const [nodeMajor] = process.versions.node.split('.').map(v => Number(v))
|
||||
|
||||
const asJsonChan = diagChan.tracingChannel('pino_asJson')
|
||||
|
||||
// JSON.stringify is faster in node 25+.
|
||||
const asString = nodeMajor >= 25 ? str => JSON.stringify(str) : _asString
|
||||
|
||||
function noop () {
|
||||
}
|
||||
|
||||
function genLog (level, hook) {
|
||||
if (!hook) return LOG
|
||||
|
||||
return function hookWrappedLog (...args) {
|
||||
hook.call(this, args, LOG, level)
|
||||
}
|
||||
|
||||
function LOG (o, ...n) {
|
||||
if (typeof o === 'object') {
|
||||
let msg = o
|
||||
if (o !== null) {
|
||||
if (o.method && o.headers && o.socket) {
|
||||
o = mapHttpRequest(o)
|
||||
} else if (typeof o.setHeader === 'function') {
|
||||
o = mapHttpResponse(o)
|
||||
}
|
||||
}
|
||||
let formatParams
|
||||
if (msg === null && n.length === 0) {
|
||||
formatParams = [null]
|
||||
} else {
|
||||
msg = n.shift()
|
||||
formatParams = n
|
||||
}
|
||||
// We do not use a coercive check for `msg` as it is
|
||||
// measurably slower than the explicit checks.
|
||||
if (typeof this[msgPrefixSym] === 'string' && msg !== undefined && msg !== null) {
|
||||
msg = this[msgPrefixSym] + msg
|
||||
}
|
||||
this[writeSym](o, format(msg, formatParams, this[formatOptsSym]), level)
|
||||
} else {
|
||||
let msg = o === undefined ? n.shift() : o
|
||||
|
||||
// We do not use a coercive check for `msg` as it is
|
||||
// measurably slower than the explicit checks.
|
||||
if (typeof this[msgPrefixSym] === 'string' && msg !== undefined && msg !== null) {
|
||||
msg = this[msgPrefixSym] + msg
|
||||
}
|
||||
this[writeSym](null, format(msg, n, this[formatOptsSym]), level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// magically escape strings for json
|
||||
// relying on their charCodeAt
|
||||
// everything below 32 needs JSON.stringify()
|
||||
// 34 and 92 happens all the time, so we
|
||||
// have a fast case for them
|
||||
function _asString (str) {
|
||||
let result = ''
|
||||
let last = 0
|
||||
let found = false
|
||||
let point = 255
|
||||
const l = str.length
|
||||
if (l > 100) {
|
||||
return JSON.stringify(str)
|
||||
}
|
||||
for (var i = 0; i < l && point >= 32; i++) {
|
||||
point = str.charCodeAt(i)
|
||||
if (point === 34 || point === 92) {
|
||||
result += str.slice(last, i) + '\\'
|
||||
last = i
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
result = str
|
||||
} else {
|
||||
result += str.slice(last)
|
||||
}
|
||||
return point < 32 ? JSON.stringify(str) : '"' + result + '"'
|
||||
}
|
||||
|
||||
/**
|
||||
* `asJson` wraps `_asJson` in order to facilitate generating diagnostics.
|
||||
*
|
||||
* @param {object} obj The merging object passed to the log method.
|
||||
* @param {string} msg The log message passed to the log method.
|
||||
* @param {number} num The log level number.
|
||||
* @param {number} time The log time in milliseconds.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
function asJson (obj, msg, num, time) {
|
||||
if (asJsonChan.hasSubscribers === false) {
|
||||
return _asJson.call(this, obj, msg, num, time)
|
||||
}
|
||||
|
||||
const store = { instance: this, arguments }
|
||||
return asJsonChan.traceSync(_asJson, store, this, obj, msg, num, time)
|
||||
}
|
||||
|
||||
/**
|
||||
* `_asJson` parses all collected data and generates the finalized newline
|
||||
* delimited JSON string.
|
||||
*
|
||||
* @param {object} obj The merging object passed to the log method.
|
||||
* @param {string} msg The log message passed to the log method.
|
||||
* @param {number} num The log level number.
|
||||
* @param {number} time The log time in milliseconds.
|
||||
*
|
||||
* @returns {string} The finalized log string terminated with a newline.
|
||||
* @private
|
||||
*/
|
||||
function _asJson (obj, msg, num, time) {
|
||||
const stringify = this[stringifySym]
|
||||
const stringifySafe = this[stringifySafeSym]
|
||||
const stringifiers = this[stringifiersSym]
|
||||
const end = this[endSym]
|
||||
const chindings = this[chindingsSym]
|
||||
const serializers = this[serializersSym]
|
||||
const formatters = this[formattersSym]
|
||||
const messageKey = this[messageKeySym]
|
||||
const errorKey = this[errorKeySym]
|
||||
let data = this[lsCacheSym][num] + time
|
||||
|
||||
// we need the child bindings added to the output first so instance logged
|
||||
// objects can take precedence when JSON.parse-ing the resulting log line
|
||||
data = data + chindings
|
||||
|
||||
let value
|
||||
if (formatters.log) {
|
||||
obj = formatters.log(obj)
|
||||
}
|
||||
const wildcardStringifier = stringifiers[wildcardFirstSym]
|
||||
let propStr = ''
|
||||
for (const key in obj) {
|
||||
value = obj[key]
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key) && value !== undefined) {
|
||||
if (serializers[key]) {
|
||||
value = serializers[key](value)
|
||||
} else if (key === errorKey && serializers.err) {
|
||||
value = serializers.err(value)
|
||||
}
|
||||
|
||||
const stringifier = stringifiers[key] || wildcardStringifier
|
||||
|
||||
switch (typeof value) {
|
||||
case 'undefined':
|
||||
case 'function':
|
||||
continue
|
||||
case 'number':
|
||||
/* eslint no-fallthrough: "off" */
|
||||
if (Number.isFinite(value) === false) {
|
||||
value = null
|
||||
}
|
||||
// this case explicitly falls through to the next one
|
||||
case 'boolean':
|
||||
if (stringifier) value = stringifier(value)
|
||||
break
|
||||
case 'string':
|
||||
value = (stringifier || asString)(value)
|
||||
break
|
||||
default:
|
||||
value = (stringifier || stringify)(value, stringifySafe)
|
||||
}
|
||||
if (value === undefined) continue
|
||||
const strKey = asString(key)
|
||||
propStr += ',' + strKey + ':' + value
|
||||
}
|
||||
}
|
||||
|
||||
let msgStr = ''
|
||||
if (msg !== undefined) {
|
||||
value = serializers[messageKey] ? serializers[messageKey](msg) : msg
|
||||
const stringifier = stringifiers[messageKey] || wildcardStringifier
|
||||
|
||||
switch (typeof value) {
|
||||
case 'function':
|
||||
break
|
||||
case 'number':
|
||||
if (Number.isFinite(value) === false) {
|
||||
value = null
|
||||
}
|
||||
// this case explicitly falls through to the next one
|
||||
case 'boolean':
|
||||
if (stringifier) value = stringifier(value)
|
||||
msgStr = ',"' + messageKey + '":' + value
|
||||
break
|
||||
case 'string':
|
||||
value = (stringifier || asString)(value)
|
||||
msgStr = ',"' + messageKey + '":' + value
|
||||
break
|
||||
default:
|
||||
value = (stringifier || stringify)(value, stringifySafe)
|
||||
msgStr = ',"' + messageKey + '":' + value
|
||||
}
|
||||
}
|
||||
|
||||
if (this[nestedKeySym] && propStr) {
|
||||
// place all the obj properties under the specified key
|
||||
// the nested key is already formatted from the constructor
|
||||
return data + this[nestedKeyStrSym] + propStr.slice(1) + '}' + msgStr + end
|
||||
} else {
|
||||
return data + propStr + msgStr + end
|
||||
}
|
||||
}
|
||||
|
||||
function asChindings (instance, bindings) {
|
||||
let value
|
||||
let data = instance[chindingsSym]
|
||||
const stringify = instance[stringifySym]
|
||||
const stringifySafe = instance[stringifySafeSym]
|
||||
const stringifiers = instance[stringifiersSym]
|
||||
const wildcardStringifier = stringifiers[wildcardFirstSym]
|
||||
const serializers = instance[serializersSym]
|
||||
const formatter = instance[formattersSym].bindings
|
||||
bindings = formatter(bindings)
|
||||
|
||||
for (const key in bindings) {
|
||||
value = bindings[key]
|
||||
const valid = (key.length < 5 || (key !== 'level' &&
|
||||
key !== 'serializers' &&
|
||||
key !== 'formatters' &&
|
||||
key !== 'customLevels')) &&
|
||||
bindings.hasOwnProperty(key) &&
|
||||
value !== undefined
|
||||
if (valid === true) {
|
||||
value = serializers[key] ? serializers[key](value) : value
|
||||
value = (stringifiers[key] || wildcardStringifier || stringify)(value, stringifySafe)
|
||||
if (value === undefined) continue
|
||||
data += ',"' + key + '":' + value
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
function hasBeenTampered (stream) {
|
||||
return stream.write !== stream.constructor.prototype.write
|
||||
}
|
||||
|
||||
function buildSafeSonicBoom (opts) {
|
||||
const stream = new SonicBoom(opts)
|
||||
stream.on('error', filterBrokenPipe)
|
||||
// If we are sync: false, we must flush on exit
|
||||
if (!opts.sync && isMainThread) {
|
||||
onExit.register(stream, autoEnd)
|
||||
|
||||
stream.on('close', function () {
|
||||
onExit.unregister(stream)
|
||||
})
|
||||
}
|
||||
return stream
|
||||
|
||||
function filterBrokenPipe (err) {
|
||||
// Impossible to replicate across all operating systems
|
||||
/* istanbul ignore next */
|
||||
if (err.code === 'EPIPE') {
|
||||
// If we get EPIPE, we should stop logging here
|
||||
// however we have no control to the consumer of
|
||||
// SonicBoom, so we just overwrite the write method
|
||||
stream.write = noop
|
||||
stream.end = noop
|
||||
stream.flushSync = noop
|
||||
stream.destroy = noop
|
||||
return
|
||||
}
|
||||
stream.removeListener('error', filterBrokenPipe)
|
||||
stream.emit('error', err)
|
||||
}
|
||||
}
|
||||
|
||||
function autoEnd (stream, eventName) {
|
||||
// This check is needed only on some platforms
|
||||
/* istanbul ignore next */
|
||||
if (stream.destroyed) {
|
||||
return
|
||||
}
|
||||
|
||||
if (eventName === 'beforeExit') {
|
||||
// We still have an event loop, let's use it
|
||||
stream.flush()
|
||||
stream.on('drain', function () {
|
||||
stream.end()
|
||||
})
|
||||
} else {
|
||||
// For some reason istanbul is not detecting this, but it's there
|
||||
/* istanbul ignore next */
|
||||
// We do not have an event loop, so flush synchronously
|
||||
stream.flushSync()
|
||||
}
|
||||
}
|
||||
|
||||
function createArgsNormalizer (defaultOptions) {
|
||||
return function normalizeArgs (instance, caller, opts = {}, stream) {
|
||||
// support stream as a string
|
||||
if (typeof opts === 'string') {
|
||||
stream = buildSafeSonicBoom({ dest: opts })
|
||||
opts = {}
|
||||
} else if (typeof stream === 'string') {
|
||||
if (opts && opts.transport) {
|
||||
throw Error('only one of option.transport or stream can be specified')
|
||||
}
|
||||
stream = buildSafeSonicBoom({ dest: stream })
|
||||
} else if (opts instanceof SonicBoom || opts.writable || opts._writableState) {
|
||||
stream = opts
|
||||
opts = {}
|
||||
} else if (opts.transport) {
|
||||
if (opts.transport instanceof SonicBoom || opts.transport.writable || opts.transport._writableState) {
|
||||
throw Error('option.transport do not allow stream, please pass to option directly. e.g. pino(transport)')
|
||||
}
|
||||
if (opts.transport.targets && opts.transport.targets.length && opts.formatters && typeof opts.formatters.level === 'function') {
|
||||
throw Error('option.transport.targets do not allow custom level formatters')
|
||||
}
|
||||
|
||||
let customLevels
|
||||
if (opts.customLevels) {
|
||||
customLevels = opts.useOnlyCustomLevels ? opts.customLevels : Object.assign({}, opts.levels, opts.customLevels)
|
||||
}
|
||||
stream = transport({ caller, ...opts.transport, levels: customLevels })
|
||||
}
|
||||
opts = Object.assign({}, defaultOptions, opts)
|
||||
opts.serializers = Object.assign({}, defaultOptions.serializers, opts.serializers)
|
||||
opts.formatters = Object.assign({}, defaultOptions.formatters, opts.formatters)
|
||||
|
||||
if (opts.prettyPrint) {
|
||||
throw new Error('prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)')
|
||||
}
|
||||
|
||||
const { enabled, onChild } = opts
|
||||
if (enabled === false) opts.level = 'silent'
|
||||
if (!onChild) opts.onChild = noop
|
||||
if (!stream) {
|
||||
if (!hasBeenTampered(process.stdout)) {
|
||||
// If process.stdout.fd is undefined, it means that we are running
|
||||
// in a worker thread. Let's assume we are logging to file descriptor 1.
|
||||
stream = buildSafeSonicBoom({ fd: process.stdout.fd || 1 })
|
||||
} else {
|
||||
stream = process.stdout
|
||||
}
|
||||
}
|
||||
return { opts, stream }
|
||||
}
|
||||
}
|
||||
|
||||
function stringify (obj, stringifySafeFn) {
|
||||
try {
|
||||
return JSON.stringify(obj)
|
||||
} catch (_) {
|
||||
try {
|
||||
const stringify = stringifySafeFn || this[stringifySafeSym]
|
||||
return stringify(obj)
|
||||
} catch (_) {
|
||||
return '"[unable to serialize, circular reference is too complex to analyze]"'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildFormatters (level, bindings, log) {
|
||||
return {
|
||||
level,
|
||||
bindings,
|
||||
log
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string integer file descriptor to a proper native integer
|
||||
* file descriptor.
|
||||
*
|
||||
* @param {string} destination The file descriptor string to attempt to convert.
|
||||
*
|
||||
* @returns {Number}
|
||||
*/
|
||||
function normalizeDestFileDescriptor (destination) {
|
||||
const fd = Number(destination)
|
||||
if (typeof destination === 'string' && Number.isFinite(fd)) {
|
||||
return fd
|
||||
}
|
||||
// destination could be undefined if we are in a worker
|
||||
if (destination === undefined) {
|
||||
// This is stdout in UNIX systems
|
||||
return 1
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
noop,
|
||||
buildSafeSonicBoom,
|
||||
asChindings,
|
||||
asJson,
|
||||
genLog,
|
||||
createArgsNormalizer,
|
||||
stringify,
|
||||
buildFormatters,
|
||||
normalizeDestFileDescriptor
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# `@typescript-eslint/type-utils`
|
||||
|
||||
> Type utilities for working with TypeScript within ESLint rules.
|
||||
|
||||
[](https://www.npmjs.com/package/@typescript-eslint/utils)
|
||||
[](https://www.npmjs.com/package/@typescript-eslint/utils)
|
||||
|
||||
The utilities in this package are separated from `@typescript-eslint/utils` so that that package does not require a dependency on `typescript`.
|
||||
|
||||
> See https://typescript-eslint.io for general documentation on typescript-eslint, the tooling that allows you to run ESLint and Prettier on TypeScript code.
|
||||
|
||||
<!-- Local path for docs: docs/packages/Type_Utils.mdx -->
|
||||
@@ -0,0 +1,144 @@
|
||||
# ISC License
|
||||
#
|
||||
# Copyright (c) 2018-2025, Andrea Giammarchi, @WebReflection
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import json as _json
|
||||
|
||||
class _Known:
|
||||
def __init__(self):
|
||||
self.key = []
|
||||
self.value = []
|
||||
|
||||
class _String:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def _array_keys(value):
|
||||
for i in range(len(value)):
|
||||
yield i
|
||||
|
||||
def _object_keys(value):
|
||||
for key in value:
|
||||
yield key
|
||||
|
||||
def _is_array(value):
|
||||
return isinstance(value, (list, tuple))
|
||||
|
||||
def _is_object(value):
|
||||
return isinstance(value, dict)
|
||||
|
||||
def _is_string(value):
|
||||
return isinstance(value, str)
|
||||
|
||||
def _index(known, input, value):
|
||||
input.append(value)
|
||||
index = str(len(input) - 1)
|
||||
known.key.append(value)
|
||||
known.value.append(index)
|
||||
return index
|
||||
|
||||
def _relate(known, input, value):
|
||||
if _is_string(value) or _is_array(value) or _is_object(value):
|
||||
try:
|
||||
return known.value[known.key.index(value)]
|
||||
except:
|
||||
return _index(known, input, value)
|
||||
|
||||
return value
|
||||
|
||||
def _resolver(input, lazy, parsed):
|
||||
def resolver(output):
|
||||
keys = _array_keys(output) if _is_array(output) else _object_keys(output) if _is_object(output) else []
|
||||
for key in keys:
|
||||
value = output[key]
|
||||
if isinstance(value, _String):
|
||||
tmp = input[int(value.value)]
|
||||
output[key] = tmp
|
||||
if (_is_array(tmp) or _is_object(tmp)) and tmp not in parsed:
|
||||
parsed.append(tmp)
|
||||
lazy.append([output, key])
|
||||
|
||||
return output
|
||||
|
||||
return resolver
|
||||
|
||||
def _transform(known, input, value):
|
||||
if _is_array(value):
|
||||
output = []
|
||||
for val in value:
|
||||
output.append(_relate(known, input, val))
|
||||
return output
|
||||
|
||||
if _is_object(value):
|
||||
obj = {}
|
||||
for key in value:
|
||||
obj[key] = _relate(known, input, value[key])
|
||||
return obj
|
||||
|
||||
return value
|
||||
|
||||
def _wrap(value):
|
||||
if _is_string(value):
|
||||
return _String(value)
|
||||
|
||||
if _is_array(value):
|
||||
i = 0
|
||||
for val in value:
|
||||
value[i] = _wrap(val)
|
||||
i += 1
|
||||
|
||||
elif _is_object(value):
|
||||
for key in value:
|
||||
value[key] = _wrap(value[key])
|
||||
|
||||
return value
|
||||
|
||||
def parse(value, *args, **kwargs):
|
||||
json = _json.loads(value, *args, **kwargs)
|
||||
wrapped = []
|
||||
for value in json:
|
||||
wrapped.append(_wrap(value))
|
||||
|
||||
input = []
|
||||
for value in wrapped:
|
||||
if isinstance(value, _String):
|
||||
input.append(value.value)
|
||||
else:
|
||||
input.append(value)
|
||||
|
||||
value = input[0]
|
||||
lazy = []
|
||||
revive = _resolver(input, lazy, [value])
|
||||
|
||||
value = revive(value)
|
||||
|
||||
i = 0
|
||||
while i < len(lazy):
|
||||
o, k = lazy[i]
|
||||
i += 1
|
||||
o[k] = revive(o[k])
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def stringify(value, *args, **kwargs):
|
||||
known = _Known()
|
||||
input = []
|
||||
output = []
|
||||
i = int(_index(known, input, value))
|
||||
while i < len(input):
|
||||
output.append(_transform(known, input, input[i]))
|
||||
i += 1
|
||||
return _json.dumps(output, *args, **kwargs)
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"maxdepth": 4,
|
||||
"maxstatements": 200,
|
||||
"maxcomplexity": 12,
|
||||
"maxlen": 80,
|
||||
"maxparams": 5,
|
||||
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"latedef": false,
|
||||
"noarg": true,
|
||||
"noempty": true,
|
||||
"nonew": true,
|
||||
"undef": true,
|
||||
"unused": "vars",
|
||||
"trailing": true,
|
||||
|
||||
"quotmark": true,
|
||||
"expr": true,
|
||||
"asi": true,
|
||||
|
||||
"browser": false,
|
||||
"esnext": true,
|
||||
"devel": false,
|
||||
"node": false,
|
||||
"nonstandard": false,
|
||||
|
||||
"predef": ["require", "module", "__dirname", "__filename"]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"moduleKind.d.ts","sourceRoot":"","sources":["../../src/enums/moduleKind.ts"],"names":[],"mappings":"AACA,eAAO,IAAI,UAAU,EAAE,GAAG,CAAC"}
|
||||
@@ -0,0 +1,387 @@
|
||||
/**
|
||||
* This is a fork of https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13f63c2eb8d7479caf01ab8d72f9e3683368a8f5/types/json-schema/index.d.ts
|
||||
* We intentionally fork this because:
|
||||
* - ESLint ***ONLY*** supports JSONSchema v4
|
||||
* - We want to provide stricter types
|
||||
*/
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1
|
||||
*/
|
||||
export type JSONSchema4TypeName = 'any' | 'array' | 'boolean' | 'integer' | 'null' | 'number' | 'object' | 'string';
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5
|
||||
*/
|
||||
export type JSONSchema4Type = boolean | number | string | null;
|
||||
export type JSONSchema4TypeExtended = JSONSchema4Array | JSONSchema4Object | JSONSchema4Type;
|
||||
export interface JSONSchema4Object {
|
||||
[key: string]: JSONSchema4TypeExtended;
|
||||
}
|
||||
export interface JSONSchema4Array extends Array<JSONSchema4TypeExtended> {
|
||||
}
|
||||
/**
|
||||
* Meta schema
|
||||
*
|
||||
* Recommended values:
|
||||
* - 'http://json-schema.org/schema#'
|
||||
* - 'http://json-schema.org/hyper-schema#'
|
||||
* - 'http://json-schema.org/draft-04/schema#'
|
||||
* - 'http://json-schema.org/draft-04/hyper-schema#'
|
||||
* - 'http://json-schema.org/draft-03/schema#'
|
||||
* - 'http://json-schema.org/draft-03/hyper-schema#'
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5
|
||||
*/
|
||||
export type JSONSchema4Version = string;
|
||||
/**
|
||||
* JSON Schema V4
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-04
|
||||
*/
|
||||
export type JSONSchema4 = JSONSchema4AllOfSchema | JSONSchema4AnyOfSchema | JSONSchema4AnySchema | JSONSchema4ArraySchema | JSONSchema4BooleanSchema | JSONSchema4MultiSchema | JSONSchema4NullSchema | JSONSchema4NumberSchema | JSONSchema4ObjectSchema | JSONSchema4OneOfSchema | JSONSchema4RefSchema | JSONSchema4StringSchema;
|
||||
interface JSONSchema4Base {
|
||||
/**
|
||||
* Reusable definitions that can be referenced via `$ref`
|
||||
*/
|
||||
$defs?: Record<string, JSONSchema4> | undefined;
|
||||
/**
|
||||
* Path to a schema defined in `definitions`/`$defs` that will form the base
|
||||
* for this schema.
|
||||
*
|
||||
* If you are defining an "array" schema (`schema: [ ... ]`) for your rule
|
||||
* then you should prefix this with `items/0` so that the validator can find
|
||||
* your definitions.
|
||||
*
|
||||
* eg: `'#/items/0/definitions/myDef'`
|
||||
*
|
||||
* Otherwise if you are defining an "object" schema (`schema: { ... }`) for
|
||||
* your rule you can directly reference your definitions
|
||||
*
|
||||
* eg: `'#/definitions/myDef'`
|
||||
*/
|
||||
$ref?: string | undefined;
|
||||
$schema?: JSONSchema4Version | undefined;
|
||||
/**
|
||||
* (AND) Must be valid against all of the sub-schemas
|
||||
*/
|
||||
allOf?: JSONSchema4[] | undefined;
|
||||
/**
|
||||
* (OR) Must be valid against any of the sub-schemas
|
||||
*/
|
||||
anyOf?: JSONSchema4[] | undefined;
|
||||
/**
|
||||
* The default value for the item if not present
|
||||
*/
|
||||
default?: JSONSchema4TypeExtended | undefined;
|
||||
/**
|
||||
* Reusable definitions that can be referenced via `$ref`
|
||||
*/
|
||||
definitions?: Record<string, JSONSchema4> | undefined;
|
||||
/**
|
||||
* This attribute is a string that provides a full description of the of
|
||||
* purpose the instance property.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22
|
||||
*/
|
||||
description?: string | undefined;
|
||||
/**
|
||||
* The value of this property MUST be another schema which will provide
|
||||
* a base schema which the current schema will inherit from. The
|
||||
* inheritance rules are such that any instance that is valid according
|
||||
* to the current schema MUST be valid according to the referenced
|
||||
* schema. This MAY also be an array, in which case, the instance MUST
|
||||
* be valid for all the schemas in the array. A schema that extends
|
||||
* another schema MAY define additional attributes, constrain existing
|
||||
* attributes, or add other constraints.
|
||||
*
|
||||
* Conceptually, the behavior of extends can be seen as validating an
|
||||
* instance against all constraints in the extending schema as well as
|
||||
* the extended schema(s).
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.26
|
||||
*/
|
||||
extends?: string | string[] | undefined;
|
||||
id?: string | undefined;
|
||||
/**
|
||||
* (NOT) Must not be valid against the given schema
|
||||
*/
|
||||
not?: JSONSchema4 | undefined;
|
||||
/**
|
||||
* (XOR) Must be valid against exactly one of the sub-schemas
|
||||
*/
|
||||
oneOf?: JSONSchema4[] | undefined;
|
||||
/**
|
||||
* This attribute indicates if the instance must have a value, and not
|
||||
* be undefined. This is false by default, making the instance
|
||||
* optional.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7
|
||||
*/
|
||||
required?: boolean | string[] | undefined;
|
||||
/**
|
||||
* This attribute is a string that provides a short description of the
|
||||
* instance property.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21
|
||||
*/
|
||||
title?: string | undefined;
|
||||
/**
|
||||
* A single type, or a union of simple types
|
||||
*/
|
||||
type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined;
|
||||
}
|
||||
export interface JSONSchema4RefSchema extends JSONSchema4Base {
|
||||
$ref: string;
|
||||
type?: undefined;
|
||||
}
|
||||
export interface JSONSchema4AllOfSchema extends JSONSchema4Base {
|
||||
allOf: JSONSchema4[];
|
||||
type?: undefined;
|
||||
}
|
||||
export interface JSONSchema4AnyOfSchema extends JSONSchema4Base {
|
||||
anyOf: JSONSchema4[];
|
||||
type?: undefined;
|
||||
}
|
||||
export interface JSONSchema4OneOfSchema extends JSONSchema4Base {
|
||||
oneOf: JSONSchema4[];
|
||||
type?: undefined;
|
||||
}
|
||||
export interface JSONSchema4MultiSchema extends Omit<JSONSchema4ObjectSchema, 'enum' | 'type'>, Omit<JSONSchema4ArraySchema, 'enum' | 'type'>, Omit<JSONSchema4StringSchema, 'enum' | 'type'>, Omit<JSONSchema4NumberSchema, 'enum' | 'type'>, Omit<JSONSchema4BooleanSchema, 'enum' | 'type'>, Omit<JSONSchema4NullSchema, 'enum' | 'type'>, Omit<JSONSchema4AnySchema, 'enum' | 'type'> {
|
||||
/**
|
||||
* This provides an enumeration of all possible values that are valid
|
||||
* for the instance property. This MUST be an array, and each item in
|
||||
* the array represents a possible value for the instance value. If
|
||||
* this attribute is defined, the instance value MUST be one of the
|
||||
* values in the array in order for the schema to be valid.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
|
||||
*/
|
||||
enum?: JSONSchema4Type[];
|
||||
type: JSONSchema4TypeName[];
|
||||
}
|
||||
/**
|
||||
* @see https://json-schema.org/understanding-json-schema/reference/object.html
|
||||
*/
|
||||
export interface JSONSchema4ObjectSchema extends JSONSchema4Base {
|
||||
/**
|
||||
* This attribute defines a schema for all properties that are not
|
||||
* explicitly defined in an object type definition. If specified, the
|
||||
* value MUST be a schema or a boolean. If false is provided, no
|
||||
* additional properties are allowed beyond the properties defined in
|
||||
* the schema. The default value is an empty schema which allows any
|
||||
* value for additional properties.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4
|
||||
*/
|
||||
additionalProperties?: boolean | JSONSchema4 | undefined;
|
||||
/**
|
||||
* The `dependencies` keyword conditionally applies a sub-schema when a given
|
||||
* property is present. This schema is applied in the same way `allOf` applies
|
||||
* schemas. Nothing is merged or extended. Both schemas apply independently.
|
||||
*/
|
||||
dependencies?: Record<string, JSONSchema4 | string[]> | undefined;
|
||||
/**
|
||||
* The maximum number of properties allowed for record-style schemas
|
||||
*/
|
||||
maxProperties?: number | undefined;
|
||||
/**
|
||||
* The minimum number of properties required for record-style schemas
|
||||
*/
|
||||
minProperties?: number | undefined;
|
||||
/**
|
||||
* This attribute is an object that defines the schema for a set of
|
||||
* property names of an object instance. The name of each property of
|
||||
* this attribute's object is a regular expression pattern in the ECMA
|
||||
* 262/Perl 5 format, while the value is a schema. If the pattern
|
||||
* matches the name of a property on the instance object, the value of
|
||||
* the instance's property MUST be valid against the pattern name's
|
||||
* schema value.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.3
|
||||
*/
|
||||
patternProperties?: Record<string, JSONSchema4> | undefined;
|
||||
/**
|
||||
* This attribute is an object with property definitions that define the
|
||||
* valid values of instance object property values. When the instance
|
||||
* value is an object, the property values of the instance object MUST
|
||||
* conform to the property definitions in this object. In this object,
|
||||
* each property definition's value MUST be a schema, and the property's
|
||||
* name MUST be the name of the instance property that it defines. The
|
||||
* instance property value MUST be valid according to the schema from
|
||||
* the property definition. Properties are considered unordered, the
|
||||
* order of the instance properties MAY be in any order.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.2
|
||||
*/
|
||||
properties?: Record<string, JSONSchema4> | undefined;
|
||||
type: 'object';
|
||||
}
|
||||
/**
|
||||
* @see https://json-schema.org/understanding-json-schema/reference/array.html
|
||||
*/
|
||||
export interface JSONSchema4ArraySchema extends JSONSchema4Base {
|
||||
/**
|
||||
* May only be defined when "items" is defined, and is a tuple of JSONSchemas.
|
||||
*
|
||||
* This provides a definition for additional items in an array instance
|
||||
* when tuple definitions of the items is provided. This can be false
|
||||
* to indicate additional items in the array are not allowed, or it can
|
||||
* be a schema that defines the schema of the additional items.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.6
|
||||
*/
|
||||
additionalItems?: boolean | JSONSchema4 | undefined;
|
||||
/**
|
||||
* This attribute defines the allowed items in an instance array, and
|
||||
* MUST be a schema or an array of schemas. The default value is an
|
||||
* empty schema which allows any value for items in the instance array.
|
||||
*
|
||||
* When this attribute value is a schema and the instance value is an
|
||||
* array, then all the items in the array MUST be valid according to the
|
||||
* schema.
|
||||
*
|
||||
* When this attribute value is an array of schemas and the instance
|
||||
* value is an array, each position in the instance array MUST conform
|
||||
* to the schema in the corresponding position for this array. This
|
||||
* called tuple typing. When tuple typing is used, additional items are
|
||||
* allowed, disallowed, or constrained by the "additionalItems"
|
||||
* (Section 5.6) attribute using the same rules as
|
||||
* "additionalProperties" (Section 5.4) for objects.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.5
|
||||
*/
|
||||
items?: JSONSchema4 | JSONSchema4[] | undefined;
|
||||
/**
|
||||
* Defines the maximum length of an array
|
||||
*/
|
||||
maxItems?: number | undefined;
|
||||
/**
|
||||
* Defines the minimum length of an array
|
||||
*/
|
||||
minItems?: number | undefined;
|
||||
type: 'array';
|
||||
/**
|
||||
* Enforces that all items in the array are unique
|
||||
*/
|
||||
uniqueItems?: boolean | undefined;
|
||||
}
|
||||
/**
|
||||
* @see https://json-schema.org/understanding-json-schema/reference/string.html
|
||||
*/
|
||||
export interface JSONSchema4StringSchema extends JSONSchema4Base {
|
||||
enum?: string[] | undefined;
|
||||
/**
|
||||
* The `format` keyword allows for basic semantic identification of certain
|
||||
* kinds of string values that are commonly used.
|
||||
*
|
||||
* For example, because JSON doesn’t have a “DateTime” type, dates need to be
|
||||
* encoded as strings. `format` allows the schema author to indicate that the
|
||||
* string value should be interpreted as a date.
|
||||
*
|
||||
* ajv v6 provides a few built-in formats - all other strings will cause AJV
|
||||
* to throw during schema compilation
|
||||
*/
|
||||
format?: 'date' | 'date-time' | 'email' | 'hostname' | 'ipv4' | 'ipv6' | 'json-pointer' | 'json-pointer-uri-fragment' | 'regex' | 'relative-json-pointer' | 'time' | 'uri' | 'uri-reference' | 'uri-template' | 'url' | 'uuid' | undefined;
|
||||
/**
|
||||
* The maximum allowed length for the string
|
||||
*/
|
||||
maxLength?: number | undefined;
|
||||
/**
|
||||
* The minimum allowed length for the string
|
||||
*/
|
||||
minLength?: number | undefined;
|
||||
/**
|
||||
* The `pattern` keyword is used to restrict a string to a particular regular
|
||||
* expression. The regular expression syntax is the one defined in JavaScript
|
||||
* (ECMA 262 specifically) with Unicode support.
|
||||
*
|
||||
* When defining the regular expressions, it’s important to note that the
|
||||
* string is considered valid if the expression matches anywhere within the
|
||||
* string. For example, the regular expression "p" will match any string with
|
||||
* a p in it, such as "apple" not just a string that is simply "p". Therefore,
|
||||
* it is usually less confusing, as a matter of course, to surround the
|
||||
* regular expression in ^...$, for example, "^p$", unless there is a good
|
||||
* reason not to do so.
|
||||
*/
|
||||
pattern?: string | undefined;
|
||||
type: 'string';
|
||||
}
|
||||
/**
|
||||
* @see https://json-schema.org/understanding-json-schema/reference/numeric.html
|
||||
*/
|
||||
export interface JSONSchema4NumberSchema extends JSONSchema4Base {
|
||||
/**
|
||||
* This provides an enumeration of all possible values that are valid
|
||||
* for the instance property. This MUST be an array, and each item in
|
||||
* the array represents a possible value for the instance value. If
|
||||
* this attribute is defined, the instance value MUST be one of the
|
||||
* values in the array in order for the schema to be valid.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
|
||||
*/
|
||||
enum?: number[] | undefined;
|
||||
/**
|
||||
* The exclusive minimum allowed value for the number
|
||||
* - `true` = `x < maximum`
|
||||
* - `false` = `x <= maximum`
|
||||
*
|
||||
* Default is `false`
|
||||
*/
|
||||
exclusiveMaximum?: boolean | undefined;
|
||||
/**
|
||||
* Indicates whether or not `minimum` is the inclusive or exclusive minimum
|
||||
* - `true` = `x > minimum`
|
||||
* - `false` = `x ≥ minimum`
|
||||
*
|
||||
* Default is `false`
|
||||
*/
|
||||
exclusiveMinimum?: boolean | undefined;
|
||||
/**
|
||||
* The maximum allowed value for the number
|
||||
*/
|
||||
maximum?: number | undefined;
|
||||
/**
|
||||
* The minimum allowed value for the number
|
||||
*/
|
||||
minimum?: number | undefined;
|
||||
/**
|
||||
* Numbers can be restricted to a multiple of a given number, using the
|
||||
* `multipleOf` keyword. It may be set to any positive number.
|
||||
*/
|
||||
multipleOf?: number | undefined;
|
||||
type: 'integer' | 'number';
|
||||
}
|
||||
/**
|
||||
* @see https://json-schema.org/understanding-json-schema/reference/boolean.html
|
||||
*/
|
||||
export interface JSONSchema4BooleanSchema extends JSONSchema4Base {
|
||||
/**
|
||||
* This provides an enumeration of all possible values that are valid
|
||||
* for the instance property. This MUST be an array, and each item in
|
||||
* the array represents a possible value for the instance value. If
|
||||
* this attribute is defined, the instance value MUST be one of the
|
||||
* values in the array in order for the schema to be valid.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
|
||||
*/
|
||||
enum?: boolean[] | undefined;
|
||||
type: 'boolean';
|
||||
}
|
||||
/**
|
||||
* @see https://json-schema.org/understanding-json-schema/reference/null.html
|
||||
*/
|
||||
export interface JSONSchema4NullSchema extends JSONSchema4Base {
|
||||
/**
|
||||
* This provides an enumeration of all possible values that are valid
|
||||
* for the instance property. This MUST be an array, and each item in
|
||||
* the array represents a possible value for the instance value. If
|
||||
* this attribute is defined, the instance value MUST be one of the
|
||||
* values in the array in order for the schema to be valid.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
|
||||
*/
|
||||
enum?: null[] | undefined;
|
||||
type: 'null';
|
||||
}
|
||||
export interface JSONSchema4AnySchema extends JSONSchema4Base {
|
||||
type: 'any';
|
||||
}
|
||||
export {};
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "help-me",
|
||||
"version": "5.0.0",
|
||||
"description": "Help command for node, partner of minimist and commist",
|
||||
"main": "help-me.js",
|
||||
"scripts": {
|
||||
"test": "standard && node test.js | tap-spec"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mcollina/help-me.git"
|
||||
},
|
||||
"keywords": [
|
||||
"help",
|
||||
"command",
|
||||
"minimist",
|
||||
"commist"
|
||||
],
|
||||
"author": "Matteo Collina <hello@matteocollina.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mcollina/help-me/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mcollina/help-me",
|
||||
"devDependencies": {
|
||||
"commist": "^2.0.0",
|
||||
"concat-stream": "^2.0.0",
|
||||
"pre-commit": "^1.1.3",
|
||||
"proxyquire": "^2.1.3",
|
||||
"standard": "^16.0.0",
|
||||
"tap-spec": "^5.0.0",
|
||||
"tape": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,560 @@
|
||||
var $ = Object.defineProperty;
|
||||
var C = (s) => {
|
||||
throw TypeError(s);
|
||||
};
|
||||
var D = (s, n, t) => n in s ? $(s, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[n] = t;
|
||||
var O = (s, n, t) => D(s, typeof n != "symbol" ? n + "" : n, t), q = (s, n, t) => n.has(s) || C("Cannot " + t);
|
||||
var d = (s, n, t) => (q(s, n, "read from private field"), t ? t.call(s) : n.get(s)), k = (s, n, t) => n.has(s) ? C("Cannot add the same private member more than once") : n instanceof WeakSet ? n.add(s) : n.set(s, t), f = (s, n, t, e) => (q(s, n, "write to private field"), e ? e.call(s, t) : n.set(s, t), t);
|
||||
var F = (s, n, t, e) => ({
|
||||
set _(r) {
|
||||
f(s, n, r, t);
|
||||
},
|
||||
get _() {
|
||||
return d(s, n, e);
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/.pnpm/yocto-queue@1.0.0/node_modules/yocto-queue/index.js
|
||||
var M = class {
|
||||
constructor(n) {
|
||||
O(this, "value");
|
||||
O(this, "next");
|
||||
this.value = n;
|
||||
}
|
||||
}, m, w, E, g = class {
|
||||
constructor() {
|
||||
k(this, m);
|
||||
k(this, w);
|
||||
k(this, E);
|
||||
this.clear();
|
||||
}
|
||||
enqueue(n) {
|
||||
let t = new M(n);
|
||||
d(this, m) ? (d(this, w).next = t, f(this, w, t)) : (f(this, m, t), f(this, w, t)), F(this, E)._++;
|
||||
}
|
||||
dequeue() {
|
||||
let n = d(this, m);
|
||||
if (n)
|
||||
return f(this, m, d(this, m).next), F(this, E)._--, n.value;
|
||||
}
|
||||
clear() {
|
||||
f(this, m, void 0), f(this, w, void 0), f(this, E, 0);
|
||||
}
|
||||
get size() {
|
||||
return d(this, E);
|
||||
}
|
||||
*[Symbol.iterator]() {
|
||||
let n = d(this, m);
|
||||
for (; n; )
|
||||
yield n.value, n = n.next;
|
||||
}
|
||||
};
|
||||
m = new WeakMap(), w = new WeakMap(), E = new WeakMap();
|
||||
|
||||
// node_modules/.pnpm/p-limit@4.0.0/node_modules/p-limit/index.js
|
||||
function y(s) {
|
||||
if (!((Number.isInteger(s) || s === Number.POSITIVE_INFINITY) && s > 0))
|
||||
throw new TypeError("Expected `concurrency` to be a number from 1 and up");
|
||||
let n = new g(), t = 0, e = () => {
|
||||
t--, n.size > 0 && n.dequeue()();
|
||||
}, r = async (h, p, a) => {
|
||||
t++;
|
||||
let l = (async () => h(...a))();
|
||||
p(l);
|
||||
try {
|
||||
await l;
|
||||
} catch (T) {
|
||||
}
|
||||
e();
|
||||
}, i = (h, p, a) => {
|
||||
n.enqueue(r.bind(void 0, h, p, a)), (async () => (await Promise.resolve(), t < s && n.size > 0 && n.dequeue()()))();
|
||||
}, c = (h, ...p) => new Promise((a) => {
|
||||
i(h, a, p);
|
||||
});
|
||||
return Object.defineProperties(c, {
|
||||
activeCount: {
|
||||
get: () => t
|
||||
},
|
||||
pendingCount: {
|
||||
get: () => n.size
|
||||
},
|
||||
clearQueue: {
|
||||
value: () => {
|
||||
n.clear();
|
||||
}
|
||||
}
|
||||
}), c;
|
||||
}
|
||||
|
||||
// src/event.ts
|
||||
function o(s, n = null) {
|
||||
let t = new Event(s);
|
||||
return n && Object.defineProperty(t, "task", {
|
||||
value: n,
|
||||
enumerable: !0,
|
||||
writable: !1,
|
||||
configurable: !1
|
||||
}), t;
|
||||
}
|
||||
|
||||
// src/constants.ts
|
||||
var G = {
|
||||
1: 12.71,
|
||||
2: 4.303,
|
||||
3: 3.182,
|
||||
4: 2.776,
|
||||
5: 2.571,
|
||||
6: 2.447,
|
||||
7: 2.365,
|
||||
8: 2.306,
|
||||
9: 2.262,
|
||||
10: 2.228,
|
||||
11: 2.201,
|
||||
12: 2.179,
|
||||
13: 2.16,
|
||||
14: 2.145,
|
||||
15: 2.131,
|
||||
16: 2.12,
|
||||
17: 2.11,
|
||||
18: 2.101,
|
||||
19: 2.093,
|
||||
20: 2.086,
|
||||
21: 2.08,
|
||||
22: 2.074,
|
||||
23: 2.069,
|
||||
24: 2.064,
|
||||
25: 2.06,
|
||||
26: 2.056,
|
||||
27: 2.052,
|
||||
28: 2.048,
|
||||
29: 2.045,
|
||||
30: 2.042,
|
||||
31: 2.0399,
|
||||
32: 2.0378,
|
||||
33: 2.0357,
|
||||
34: 2.0336,
|
||||
35: 2.0315,
|
||||
36: 2.0294,
|
||||
37: 2.0273,
|
||||
38: 2.0252,
|
||||
39: 2.0231,
|
||||
40: 2.021,
|
||||
41: 2.0198,
|
||||
42: 2.0186,
|
||||
43: 2.0174,
|
||||
44: 2.0162,
|
||||
45: 2.015,
|
||||
46: 2.0138,
|
||||
47: 2.0126,
|
||||
48: 2.0114,
|
||||
49: 2.0102,
|
||||
50: 2.009,
|
||||
51: 2.0081,
|
||||
52: 2.0072,
|
||||
53: 2.0063,
|
||||
54: 2.0054,
|
||||
55: 2.0045,
|
||||
56: 2.0036,
|
||||
57: 2.0027,
|
||||
58: 2.0018,
|
||||
59: 2.0009,
|
||||
60: 2,
|
||||
61: 1.9995,
|
||||
62: 1.999,
|
||||
63: 1.9985,
|
||||
64: 1.998,
|
||||
65: 1.9975,
|
||||
66: 1.997,
|
||||
67: 1.9965,
|
||||
68: 1.996,
|
||||
69: 1.9955,
|
||||
70: 1.995,
|
||||
71: 1.9945,
|
||||
72: 1.994,
|
||||
73: 1.9935,
|
||||
74: 1.993,
|
||||
75: 1.9925,
|
||||
76: 1.992,
|
||||
77: 1.9915,
|
||||
78: 1.991,
|
||||
79: 1.9905,
|
||||
80: 1.99,
|
||||
81: 1.9897,
|
||||
82: 1.9894,
|
||||
83: 1.9891,
|
||||
84: 1.9888,
|
||||
85: 1.9885,
|
||||
86: 1.9882,
|
||||
87: 1.9879,
|
||||
88: 1.9876,
|
||||
89: 1.9873,
|
||||
90: 1.987,
|
||||
91: 1.9867,
|
||||
92: 1.9864,
|
||||
93: 1.9861,
|
||||
94: 1.9858,
|
||||
95: 1.9855,
|
||||
96: 1.9852,
|
||||
97: 1.9849,
|
||||
98: 1.9846,
|
||||
99: 1.9843,
|
||||
100: 1.984,
|
||||
101: 1.9838,
|
||||
102: 1.9836,
|
||||
103: 1.9834,
|
||||
104: 1.9832,
|
||||
105: 1.983,
|
||||
106: 1.9828,
|
||||
107: 1.9826,
|
||||
108: 1.9824,
|
||||
109: 1.9822,
|
||||
110: 1.982,
|
||||
111: 1.9818,
|
||||
112: 1.9816,
|
||||
113: 1.9814,
|
||||
114: 1.9812,
|
||||
115: 1.9819,
|
||||
116: 1.9808,
|
||||
117: 1.9806,
|
||||
118: 1.9804,
|
||||
119: 1.9802,
|
||||
120: 1.98,
|
||||
infinity: 1.96
|
||||
}, N = G;
|
||||
|
||||
// src/utils.ts
|
||||
var J = (s) => s / 1e6, U = () => J(Number(process.hrtime.bigint())), B = () => performance.now();
|
||||
function W(s) {
|
||||
return s !== null && typeof s == "object" && typeof s.then == "function";
|
||||
}
|
||||
var S = (s, n) => s.reduce((e, r) => e + (r - n) ** 2, 0) / (s.length - 1) || 0, X = (async () => {
|
||||
}).constructor, Z = (s) => s.constructor === X, z = async (s) => {
|
||||
if (Z(s.fn))
|
||||
return !0;
|
||||
try {
|
||||
if (s.opts.beforeEach != null)
|
||||
try {
|
||||
await s.opts.beforeEach.call(s);
|
||||
} catch (e) {
|
||||
}
|
||||
let n = s.fn(), t = W(n);
|
||||
if (t)
|
||||
try {
|
||||
await n;
|
||||
} catch (e) {
|
||||
}
|
||||
if (s.opts.afterEach != null)
|
||||
try {
|
||||
await s.opts.afterEach.call(s);
|
||||
} catch (e) {
|
||||
}
|
||||
return t;
|
||||
} catch (n) {
|
||||
return !1;
|
||||
}
|
||||
};
|
||||
|
||||
// src/task.ts
|
||||
var b = class extends EventTarget {
|
||||
constructor(t, e, r, i = {}) {
|
||||
super();
|
||||
/*
|
||||
* the number of times the task
|
||||
* function has been executed
|
||||
*/
|
||||
this.runs = 0;
|
||||
this.bench = t, this.name = e, this.fn = r, this.opts = i;
|
||||
}
|
||||
async loop(t, e) {
|
||||
var T;
|
||||
let r = this.bench.concurrency === "task", { threshold: i } = this.bench, c = 0, h = [];
|
||||
if (this.opts.beforeAll != null)
|
||||
try {
|
||||
await this.opts.beforeAll.call(this);
|
||||
} catch (u) {
|
||||
return { error: u };
|
||||
}
|
||||
let p = await z(this), a = async () => {
|
||||
this.opts.beforeEach != null && await this.opts.beforeEach.call(this);
|
||||
let u = 0;
|
||||
if (p) {
|
||||
let v = this.bench.now();
|
||||
await this.fn.call(this), u = this.bench.now() - v;
|
||||
} else {
|
||||
let v = this.bench.now();
|
||||
this.fn.call(this), u = this.bench.now() - v;
|
||||
}
|
||||
h.push(u), c += u, this.opts.afterEach != null && await this.opts.afterEach.call(this);
|
||||
}, l = y(i);
|
||||
try {
|
||||
let u = [];
|
||||
for (; (c < t || h.length + l.activeCount + l.pendingCount < e) && !((T = this.bench.signal) != null && T.aborted); )
|
||||
r ? u.push(l(a)) : await a();
|
||||
u.length && await Promise.all(u);
|
||||
} catch (u) {
|
||||
return { error: u };
|
||||
}
|
||||
if (this.opts.afterAll != null)
|
||||
try {
|
||||
await this.opts.afterAll.call(this);
|
||||
} catch (u) {
|
||||
return { error: u };
|
||||
}
|
||||
return { samples: h };
|
||||
}
|
||||
/**
|
||||
* run the current task and write the results in `Task.result` object
|
||||
*/
|
||||
async run() {
|
||||
var r, i;
|
||||
if ((r = this.result) != null && r.error)
|
||||
return this;
|
||||
this.dispatchEvent(o("start", this)), await this.bench.setup(this, "run");
|
||||
let { samples: t, error: e } = await this.loop(this.bench.time, this.bench.iterations);
|
||||
if (this.bench.teardown(this, "run"), t) {
|
||||
let c = t.reduce((L, A) => L + A, 0);
|
||||
this.runs = t.length, t.sort((L, A) => L - A);
|
||||
let h = c / this.runs, p = 1e3 / h, a = t.length, l = a - 1, T = t[0], u = t[l], v = c / t.length || 0, P = S(t, v), R = Math.sqrt(P), I = R / Math.sqrt(a), _ = N[String(Math.round(l) || 1)] || N.infinity, K = I * _, j = K / v * 100, H = t[Math.ceil(a * 0.75) - 1], V = t[Math.ceil(a * 0.99) - 1], Q = t[Math.ceil(a * 0.995) - 1], Y = t[Math.ceil(a * 0.999) - 1];
|
||||
if ((i = this.bench.signal) != null && i.aborted)
|
||||
return this;
|
||||
this.setResult({
|
||||
totalTime: c,
|
||||
min: T,
|
||||
max: u,
|
||||
hz: p,
|
||||
period: h,
|
||||
samples: t,
|
||||
mean: v,
|
||||
variance: P,
|
||||
sd: R,
|
||||
sem: I,
|
||||
df: l,
|
||||
critical: _,
|
||||
moe: K,
|
||||
rme: j,
|
||||
p75: H,
|
||||
p99: V,
|
||||
p995: Q,
|
||||
p999: Y
|
||||
});
|
||||
}
|
||||
if (e) {
|
||||
if (this.setResult({ error: e }), this.bench.throws)
|
||||
throw e;
|
||||
this.dispatchEvent(o("error", this)), this.bench.dispatchEvent(o("error", this));
|
||||
}
|
||||
return this.dispatchEvent(o("cycle", this)), this.bench.dispatchEvent(o("cycle", this)), this.dispatchEvent(o("complete", this)), this;
|
||||
}
|
||||
/**
|
||||
* warmup the current task
|
||||
*/
|
||||
async warmup() {
|
||||
var e;
|
||||
if ((e = this.result) != null && e.error)
|
||||
return;
|
||||
this.dispatchEvent(o("warmup", this)), await this.bench.setup(this, "warmup");
|
||||
let { error: t } = await this.loop(this.bench.warmupTime, this.bench.warmupIterations);
|
||||
if (this.bench.teardown(this, "warmup"), t && (this.setResult({ error: t }), this.bench.throws))
|
||||
throw t;
|
||||
}
|
||||
addEventListener(t, e, r) {
|
||||
super.addEventListener(t, e, r);
|
||||
}
|
||||
removeEventListener(t, e, r) {
|
||||
super.removeEventListener(t, e, r);
|
||||
}
|
||||
/**
|
||||
* change the result object values
|
||||
*/
|
||||
setResult(t) {
|
||||
this.result = { ...this.result, ...t }, Object.freeze(this.result);
|
||||
}
|
||||
/**
|
||||
* reset the task to make the `Task.runs` a zero-value and remove the `Task.result`
|
||||
* object
|
||||
*/
|
||||
reset() {
|
||||
this.dispatchEvent(o("reset", this)), this.runs = 0, this.result = void 0;
|
||||
}
|
||||
};
|
||||
|
||||
// src/bench.ts
|
||||
var x = class extends EventTarget {
|
||||
constructor(t = {}) {
|
||||
var e, r, i, c, h, p, a, l;
|
||||
super();
|
||||
/*
|
||||
* @private the task map
|
||||
*/
|
||||
this._tasks = /* @__PURE__ */ new Map();
|
||||
this._todos = /* @__PURE__ */ new Map();
|
||||
/**
|
||||
* Executes tasks concurrently based on the specified concurrency mode.
|
||||
*
|
||||
* - When `mode` is set to `null` (default), concurrency is disabled.
|
||||
* - When `mode` is set to 'task', each task's iterations (calls of a task function) run concurrently.
|
||||
* - When `mode` is set to 'bench', different tasks within the bench run concurrently.
|
||||
*/
|
||||
this.concurrency = null;
|
||||
/**
|
||||
* The maximum number of concurrent tasks to run. Defaults to Infinity.
|
||||
*/
|
||||
this.threshold = 1 / 0;
|
||||
this.warmupTime = 100;
|
||||
this.warmupIterations = 5;
|
||||
this.time = 500;
|
||||
this.iterations = 10;
|
||||
this.now = B;
|
||||
this.now = (e = t.now) != null ? e : this.now, this.warmupTime = (r = t.warmupTime) != null ? r : this.warmupTime, this.warmupIterations = (i = t.warmupIterations) != null ? i : this.warmupIterations, this.time = (c = t.time) != null ? c : this.time, this.iterations = (h = t.iterations) != null ? h : this.iterations, this.signal = t.signal, this.throws = (p = t.throws) != null ? p : !1, this.setup = (a = t.setup) != null ? a : () => {
|
||||
}, this.teardown = (l = t.teardown) != null ? l : () => {
|
||||
}, this.signal && this.signal.addEventListener(
|
||||
"abort",
|
||||
() => {
|
||||
this.dispatchEvent(o("abort"));
|
||||
},
|
||||
{ once: !0 }
|
||||
);
|
||||
}
|
||||
runTask(t) {
|
||||
var e;
|
||||
return (e = this.signal) != null && e.aborted ? t : t.run();
|
||||
}
|
||||
/**
|
||||
* run the added tasks that were registered using the
|
||||
* {@link add} method.
|
||||
* Note: This method does not do any warmup. Call {@link warmup} for that.
|
||||
*/
|
||||
async run() {
|
||||
if (this.concurrency === "bench")
|
||||
return this.runConcurrently(this.threshold, this.concurrency);
|
||||
this.dispatchEvent(o("start"));
|
||||
let t = [];
|
||||
for (let e of [...this._tasks.values()])
|
||||
t.push(await this.runTask(e));
|
||||
return this.dispatchEvent(o("complete")), t;
|
||||
}
|
||||
/**
|
||||
* See Bench.{@link concurrency}
|
||||
*/
|
||||
async runConcurrently(t = 1 / 0, e = "bench") {
|
||||
if (this.threshold = t, this.concurrency = e, e === "task")
|
||||
return this.run();
|
||||
this.dispatchEvent(o("start"));
|
||||
let r = y(t), i = [];
|
||||
for (let h of [...this._tasks.values()])
|
||||
i.push(r(() => this.runTask(h)));
|
||||
let c = await Promise.all(i);
|
||||
return this.dispatchEvent(o("complete")), c;
|
||||
}
|
||||
/**
|
||||
* warmup the benchmark tasks.
|
||||
* This is not run by default by the {@link run} method.
|
||||
*/
|
||||
async warmup() {
|
||||
if (this.concurrency === "bench") {
|
||||
await this.warmupConcurrently(this.threshold, this.concurrency);
|
||||
return;
|
||||
}
|
||||
this.dispatchEvent(o("warmup"));
|
||||
for (let [, t] of this._tasks)
|
||||
await t.warmup();
|
||||
}
|
||||
/**
|
||||
* warmup the benchmark tasks concurrently.
|
||||
* This is not run by default by the {@link runConcurrently} method.
|
||||
*/
|
||||
async warmupConcurrently(t = 1 / 0, e = "bench") {
|
||||
if (this.threshold = t, this.concurrency = e, e === "task") {
|
||||
await this.warmup();
|
||||
return;
|
||||
}
|
||||
this.dispatchEvent(o("warmup"));
|
||||
let r = y(t), i = [];
|
||||
for (let [, c] of this._tasks)
|
||||
i.push(r(() => c.warmup()));
|
||||
await Promise.all(i);
|
||||
}
|
||||
/**
|
||||
* reset each task and remove its result
|
||||
*/
|
||||
reset() {
|
||||
this.dispatchEvent(o("reset")), this._tasks.forEach((t) => {
|
||||
t.reset();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* add a benchmark task to the task map
|
||||
*/
|
||||
add(t, e, r = {}) {
|
||||
let i = new b(this, t, e, r);
|
||||
return this._tasks.set(t, i), this.dispatchEvent(o("add", i)), this;
|
||||
}
|
||||
/**
|
||||
* add a benchmark todo to the todo map
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
todo(t, e = () => {
|
||||
}, r = {}) {
|
||||
let i = new b(this, t, e, r);
|
||||
return this._todos.set(t, i), this.dispatchEvent(o("todo", i)), this;
|
||||
}
|
||||
/**
|
||||
* remove a benchmark task from the task map
|
||||
*/
|
||||
remove(t) {
|
||||
let e = this.getTask(t);
|
||||
return e && (this.dispatchEvent(o("remove", e)), this._tasks.delete(t)), this;
|
||||
}
|
||||
addEventListener(t, e, r) {
|
||||
super.addEventListener(t, e, r);
|
||||
}
|
||||
removeEventListener(t, e, r) {
|
||||
super.removeEventListener(t, e, r);
|
||||
}
|
||||
/**
|
||||
* table of the tasks results
|
||||
*/
|
||||
table(t) {
|
||||
return this.tasks.map((e) => {
|
||||
if (e.result) {
|
||||
if (e.result.error)
|
||||
throw e.result.error;
|
||||
return (t == null ? void 0 : t(e)) || {
|
||||
"Task Name": e.name,
|
||||
"ops/sec": e.result.error ? "NaN" : parseInt(e.result.hz.toString(), 10).toLocaleString(),
|
||||
"Average Time (ns)": e.result.error ? "NaN" : e.result.mean * 1e3 * 1e3,
|
||||
Margin: e.result.error ? "NaN" : `\xB1${e.result.rme.toFixed(2)}%`,
|
||||
Samples: e.result.error ? "NaN" : e.result.samples.length
|
||||
};
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* (getter) tasks results as an array
|
||||
*/
|
||||
get results() {
|
||||
return [...this._tasks.values()].map((t) => t.result);
|
||||
}
|
||||
/**
|
||||
* (getter) tasks as an array
|
||||
*/
|
||||
get tasks() {
|
||||
return [...this._tasks.values()];
|
||||
}
|
||||
get todos() {
|
||||
return [...this._todos.values()];
|
||||
}
|
||||
/**
|
||||
* get a task based on the task name
|
||||
*/
|
||||
getTask(t) {
|
||||
return this._tasks.get(t);
|
||||
}
|
||||
};
|
||||
export {
|
||||
x as Bench,
|
||||
b as Task,
|
||||
U as hrtimeNow,
|
||||
B as now
|
||||
};
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow returning values from Promise executor functions
|
||||
* @author Milos Djermanovic
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const functionTypesToCheck = new Set([
|
||||
"ArrowFunctionExpression",
|
||||
"FunctionExpression",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Determines whether the given function node is used as a Promise executor.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @param {SourceCode} sourceCode Source code to which the node belongs.
|
||||
* @returns {boolean} `true` if the node is a Promise executor.
|
||||
*/
|
||||
function isPromiseExecutor(node, sourceCode) {
|
||||
const parent = node.parent;
|
||||
|
||||
return (
|
||||
parent.type === "NewExpression" &&
|
||||
parent.arguments[0] === node &&
|
||||
parent.callee.type === "Identifier" &&
|
||||
parent.callee.name === "Promise" &&
|
||||
sourceCode.isGlobalReference(parent.callee)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given node is a void expression.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {boolean} - `true` if the node is a void expression
|
||||
*/
|
||||
function expressionIsVoid(node) {
|
||||
return node.type === "UnaryExpression" && node.operator === "void";
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes the linting error by prepending "void " to the given node
|
||||
* @param {Object} sourceCode context given by context.sourceCode
|
||||
* @param {ASTNode} node The node to fix.
|
||||
* @param {Object} fixer The fixer object provided by ESLint.
|
||||
* @returns {Array<Object>} - An array of fix objects to apply to the node.
|
||||
*/
|
||||
function voidPrependFixer(sourceCode, node, fixer) {
|
||||
const requiresParens =
|
||||
// prepending `void ` will fail if the node has a lower precedence than void
|
||||
astUtils.getPrecedence(node) <
|
||||
astUtils.getPrecedence({
|
||||
type: "UnaryExpression",
|
||||
operator: "void",
|
||||
}) &&
|
||||
// check if there are parentheses around the node to avoid redundant parentheses
|
||||
!astUtils.isParenthesised(sourceCode, node);
|
||||
|
||||
// avoid parentheses issues
|
||||
const returnOrArrowToken = sourceCode.getTokenBefore(
|
||||
node,
|
||||
node.parent.type === "ArrowFunctionExpression"
|
||||
? astUtils.isArrowToken
|
||||
: // isReturnToken
|
||||
token => token.type === "Keyword" && token.value === "return",
|
||||
);
|
||||
|
||||
const firstToken = sourceCode.getTokenAfter(returnOrArrowToken);
|
||||
|
||||
const prependSpace =
|
||||
// is return token, as => allows void to be adjacent
|
||||
returnOrArrowToken.value === "return" &&
|
||||
// If two tokens (return and "(") are adjacent
|
||||
returnOrArrowToken.range[1] === firstToken.range[0];
|
||||
|
||||
return [
|
||||
fixer.insertTextBefore(
|
||||
firstToken,
|
||||
`${prependSpace ? " " : ""}void ${requiresParens ? "(" : ""}`,
|
||||
),
|
||||
fixer.insertTextAfter(node, requiresParens ? ")" : ""),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes the linting error by `wrapping {}` around the given node's body.
|
||||
* @param {Object} sourceCode context given by context.sourceCode
|
||||
* @param {ASTNode} node The node to fix.
|
||||
* @param {Object} fixer The fixer object provided by ESLint.
|
||||
* @returns {Array<Object>} - An array of fix objects to apply to the node.
|
||||
*/
|
||||
function curlyWrapFixer(sourceCode, node, fixer) {
|
||||
// https://github.com/eslint/eslint/pull/17282#issuecomment-1592795923
|
||||
const arrowToken = sourceCode.getTokenBefore(
|
||||
node.body,
|
||||
astUtils.isArrowToken,
|
||||
);
|
||||
const firstToken = sourceCode.getTokenAfter(arrowToken);
|
||||
const lastToken = sourceCode.getLastToken(node);
|
||||
|
||||
return [
|
||||
fixer.insertTextBefore(firstToken, "{"),
|
||||
fixer.insertTextAfter(lastToken, "}"),
|
||||
];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
defaultOptions: [
|
||||
{
|
||||
allowVoid: false,
|
||||
},
|
||||
],
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow returning values from Promise executor functions",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-promise-executor-return",
|
||||
},
|
||||
|
||||
hasSuggestions: true,
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
allowVoid: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
returnsValue:
|
||||
"Return values from promise executor functions cannot be read.",
|
||||
|
||||
// arrow and function suggestions
|
||||
prependVoid: "Prepend `void` to the expression.",
|
||||
|
||||
// only arrow suggestions
|
||||
wrapBraces: "Wrap the expression in `{}`.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
let funcInfo = null;
|
||||
const sourceCode = context.sourceCode;
|
||||
const [{ allowVoid }] = context.options;
|
||||
|
||||
return {
|
||||
onCodePathStart(_, node) {
|
||||
funcInfo = {
|
||||
upper: funcInfo,
|
||||
shouldCheck:
|
||||
functionTypesToCheck.has(node.type) &&
|
||||
isPromiseExecutor(node, sourceCode),
|
||||
};
|
||||
|
||||
if (
|
||||
// Is a Promise executor
|
||||
funcInfo.shouldCheck &&
|
||||
node.type === "ArrowFunctionExpression" &&
|
||||
node.expression &&
|
||||
// Except void
|
||||
!(allowVoid && expressionIsVoid(node.body))
|
||||
) {
|
||||
const suggest = [];
|
||||
|
||||
// prevent useless refactors
|
||||
if (allowVoid) {
|
||||
suggest.push({
|
||||
messageId: "prependVoid",
|
||||
fix(fixer) {
|
||||
return voidPrependFixer(
|
||||
sourceCode,
|
||||
node.body,
|
||||
fixer,
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Do not suggest wrapping an unnamed function or class expression in braces as that would be invalid syntax.
|
||||
if (!(
|
||||
(node.body.type === "FunctionExpression" ||
|
||||
node.body.type === "ClassExpression") &&
|
||||
!node.body.id
|
||||
)) {
|
||||
suggest.push({
|
||||
messageId: "wrapBraces",
|
||||
fix(fixer) {
|
||||
return curlyWrapFixer(sourceCode, node, fixer);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
context.report({
|
||||
node: node.body,
|
||||
messageId: "returnsValue",
|
||||
suggest,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onCodePathEnd() {
|
||||
funcInfo = funcInfo.upper;
|
||||
},
|
||||
|
||||
ReturnStatement(node) {
|
||||
if (!(funcInfo.shouldCheck && node.argument)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// node is `return <expression>`
|
||||
if (!allowVoid) {
|
||||
context.report({ node, messageId: "returnsValue" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (expressionIsVoid(node.argument)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// allowVoid && !expressionIsVoid
|
||||
context.report({
|
||||
node,
|
||||
messageId: "returnsValue",
|
||||
suggest: [
|
||||
{
|
||||
messageId: "prependVoid",
|
||||
fix(fixer) {
|
||||
return voidPrependFixer(
|
||||
sourceCode,
|
||||
node.argument,
|
||||
fixer,
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
# Benchmarks
|
||||
|
||||
`pino.info('hello world')`:
|
||||
|
||||
```
|
||||
|
||||
BASIC benchmark averages
|
||||
Bunyan average: 377.434ms
|
||||
Winston average: 270.249ms
|
||||
Bole average: 172.690ms
|
||||
Debug average: 220.527ms
|
||||
LogLevel average: 222.802ms
|
||||
Pino average: 114.801ms
|
||||
PinoMinLength average: 70.968ms
|
||||
PinoNodeStream average: 159.192ms
|
||||
|
||||
```
|
||||
|
||||
`pino.info({'hello': 'world'})`:
|
||||
|
||||
```
|
||||
|
||||
OBJECT benchmark averages
|
||||
BunyanObj average: 410.379ms
|
||||
WinstonObj average: 273.120ms
|
||||
BoleObj average: 185.069ms
|
||||
LogLevelObject average: 433.425ms
|
||||
PinoObj average: 119.315ms
|
||||
PinoMinLengthObj average: 76.968ms
|
||||
PinoNodeStreamObj average: 164.268ms
|
||||
|
||||
```
|
||||
|
||||
`pino.info(aBigDeeplyNestedObject)`:
|
||||
|
||||
```
|
||||
|
||||
DEEP-OBJECT benchmark averages
|
||||
BunyanDeepObj average: 1.839ms
|
||||
WinstonDeepObj average: 5.604ms
|
||||
BoleDeepObj average: 3.422ms
|
||||
LogLevelDeepObj average: 11.716ms
|
||||
PinoDeepObj average: 2.256ms
|
||||
PinoMinLengthDeepObj average: 2.240ms
|
||||
PinoNodeStreamDeepObj average: 2.595ms
|
||||
|
||||
```
|
||||
|
||||
`pino.info('hello %s %j %d', 'world', {obj: true}, 4, {another: 'obj'})`:
|
||||
|
||||
For a fair comparison, [LogLevel](http://npm.im/loglevel) was extended
|
||||
to include a timestamp and [bole](http://npm.im/bole) had
|
||||
`fastTime` mode switched on.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,423 @@
|
||||
<a id="intro"></a>
|
||||
# pino-pretty
|
||||
|
||||
[](https://www.npmjs.com/package/pino-pretty)
|
||||
[](https://github.com/pinojs/pino-pretty/actions?query=workflow%3ACI)
|
||||
[](https://coveralls.io/github/pinojs/pino-pretty?branch=master)
|
||||
[](https://standardjs.com/)
|
||||
|
||||
This module provides a basic [ndjson](https://github.com/ndjson/ndjson-spec) formatter to be used in __development__. If an
|
||||
incoming line looks like it could be a log line from an ndjson logger, in
|
||||
particular the [Pino](https://getpino.io/) logging library, then it will apply
|
||||
extra formatting by considering things like the log level and timestamp.
|
||||
|
||||
A standard Pino log line like:
|
||||
|
||||
```
|
||||
{"level":30,"time":1522431328992,"msg":"hello world","pid":42,"hostname":"foo","v":1}
|
||||
```
|
||||
|
||||
Will format to:
|
||||
|
||||
```
|
||||
[17:35:28.992] INFO (42): hello world
|
||||
```
|
||||
|
||||
If you landed on this page due to the deprecation of the `prettyPrint` option
|
||||
of `pino`, read the [Programmatic Integration](#integration) section.
|
||||
|
||||
<a id="example"></a>
|
||||
## Example
|
||||
|
||||
Using the [example script][exscript] from the Pino module, we can see what the
|
||||
prettified logs will look like:
|
||||
|
||||

|
||||
|
||||
[exscript]: https://github.com/pinojs/pino/blob/25ba61f40ea5a1a753c85002812426d765da52a4/examples/basic.js
|
||||
|
||||
<a id="install"></a>
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install -g pino-pretty
|
||||
```
|
||||
|
||||
<a id="usage"></a>
|
||||
## Usage
|
||||
|
||||
It is recommended to use `pino-pretty` with `pino`
|
||||
by piping output to the CLI tool:
|
||||
|
||||
```sh
|
||||
node app.js | pino-pretty
|
||||
```
|
||||
|
||||
<a id="cliargs"></a>
|
||||
### CLI Arguments
|
||||
|
||||
- `--colorize` (`-c`): Adds terminal color escape sequences to the output.
|
||||
- `--no-colorizeObjects`: Suppress colorization of objects.
|
||||
- `--crlf` (`-f`): Appends carriage return and line feed, instead of just a line
|
||||
feed, to the formatted log line.
|
||||
- `--errorProps` (`-e`): When formatting an error object, display this list
|
||||
of properties. The list should be a comma-separated list of properties Default: `''`.
|
||||
Do not use this option if logging from pino@7. Support will be removed from future versions.
|
||||
- `--levelFirst` (`-l`): Display the log level name before the logged date and time.
|
||||
- `--errorLikeObjectKeys` (`-k`): Define the log keys that are associated with
|
||||
error like objects. Default: `err,error`.
|
||||
- `--messageKey` (`-m`): Define the key that contains the main log message.
|
||||
Default: `msg`.
|
||||
- `--levelKey` (`--levelKey`): Define the key that contains the level of the log. Nested keys are supported with each property delimited by a dot character (`.`).
|
||||
Keys may be escaped to target property names that contains the delimiter itself:
|
||||
(`--levelKey tags\\.level`).
|
||||
Default: `level`.
|
||||
- `--levelLabel` (`-b`): Output the log level using the specified label.
|
||||
Default: `levelLabel`.
|
||||
- `--minimumLevel` (`-L`): Hide messages below the specified log level. Accepts a number, `trace`, `debug`, `info`, `warn`, `error`, or `fatal`. If any more filtering is required, consider using [`jq`](https://stedolan.github.io/jq/).
|
||||
- `--customLevels` (`-x`): Override default levels with custom levels, e.g. `-x err:99,info:1`
|
||||
- `--customColors` (`-X`): Override default colors with custom colors, e.g. `-X err:red,info:blue`
|
||||
- `--useOnlyCustomProps` (`-U`): Only use custom levels and colors (if provided) (default: true); else fallback to default levels and colors, e.g. `-U false`
|
||||
- `--messageFormat` (`-o`): Format output of message, e.g. `{levelLabel} - {pid} - url:{req.url}` will output message: `INFO - 1123 - url:localhost:3000/test`
|
||||
Default: `false`
|
||||
- `--timestampKey` (`-a`): Define the key that contains the log timestamp.
|
||||
Default: `time`.
|
||||
- `--translateTime` (`-t`): Translate the epoch time value into a human-readable
|
||||
date and time string. This flag also can set the format string to apply when
|
||||
translating the date to a human-readable format. For a list of available pattern
|
||||
letters, see the [`dateformat` documentation](https://www.npmjs.com/package/dateformat).
|
||||
- The default format is `HH:MM:ss.l` in the local timezone.
|
||||
- Require a `UTC:` prefix to translate time to UTC, e.g. `UTC:yyyy-mm-dd HH:MM:ss.l o`.
|
||||
- Require a `SYS:` prefix to translate time to the local system's time zone. A
|
||||
shortcut `SYS:standard` to translate time to `yyyy-mm-dd HH:MM:ss.l o` in
|
||||
system time zone.
|
||||
- `--ignore` (`-i`): Ignore one or several keys, nested keys are supported with each property delimited by a dot character (`.`),
|
||||
keys may be escaped to target property names that contains the delimiter itself:
|
||||
(`-i time,hostname,req.headers,log\\.domain\\.corp/foo`).
|
||||
The `--ignore` option would be ignored, if both `--ignore` and `--include` are passed.
|
||||
Default: `hostname`.
|
||||
- `--include` (`-I`): The opposite of `--ignore`. Include one or several keys.
|
||||
- `--hideObject` (`-H`): Hide objects from output (but not error object)
|
||||
- `--singleLine` (`-S`): Print each log message on a single line (errors will still be multi-line)
|
||||
- `--config`: Specify a path to a config file containing the pino-pretty options. pino-pretty will attempt to read from a `.pino-prettyrc` in your current directory (`process.cwd`) if not specified
|
||||
|
||||
<a id="integration"></a>
|
||||
## Programmatic Integration
|
||||
|
||||
We recommend against using `pino-pretty` in production and highly
|
||||
recommend installing `pino-pretty` as a development dependency.
|
||||
|
||||
```bash
|
||||
npm install --save-dev pino-pretty
|
||||
```
|
||||
|
||||
Install `pino-pretty` alongside `pino` and set the transport target to `'pino-pretty'`:
|
||||
|
||||
```js
|
||||
const pino = require('pino')
|
||||
const logger = pino({
|
||||
transport: {
|
||||
target: 'pino-pretty'
|
||||
},
|
||||
})
|
||||
|
||||
logger.info('hi')
|
||||
```
|
||||
|
||||
The transport option can also have an options object containing `pino-pretty` options:
|
||||
|
||||
```js
|
||||
const pino = require('pino')
|
||||
const logger = pino({
|
||||
transport: {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
colorize: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
logger.info('hi')
|
||||
```
|
||||
|
||||
Use it as a stream:
|
||||
|
||||
```js
|
||||
const pino = require('pino')
|
||||
const pretty = require('pino-pretty')
|
||||
const logger = pino(pretty())
|
||||
|
||||
logger.info('hi')
|
||||
```
|
||||
|
||||
Options are also supported:
|
||||
|
||||
```js
|
||||
const pino = require('pino')
|
||||
const pretty = require('pino-pretty')
|
||||
const stream = pretty({
|
||||
colorize: true
|
||||
})
|
||||
const logger = pino(stream)
|
||||
|
||||
logger.info('hi')
|
||||
```
|
||||
|
||||
See the [Options](#options) section for all possible options.
|
||||
|
||||
The following configuration ensures that `pino-pretty` is activated only in development mode.
|
||||
|
||||
```js
|
||||
const pino = require('pino')
|
||||
|
||||
// Define the transport configuration only when the output stream is connected to a TTY
|
||||
const transport =
|
||||
process.stdout.isTTY
|
||||
? { transport: { target: 'pino-pretty' } }
|
||||
: {};
|
||||
|
||||
const logger = pino({
|
||||
...transport
|
||||
})
|
||||
|
||||
logger.info('hi')
|
||||
```
|
||||
|
||||
### Usage as a stream
|
||||
|
||||
If you are using `pino-pretty` as a stream and you need to provide options to `pino`,
|
||||
pass the options as the first argument and `pino-pretty` as second argument:
|
||||
|
||||
```js
|
||||
const pino = require('pino')
|
||||
const pretty = require('pino-pretty')
|
||||
const stream = pretty({
|
||||
colorize: true
|
||||
})
|
||||
const logger = pino({ level: 'info' }, stream)
|
||||
|
||||
// Nothing is printed
|
||||
logger.debug('hi')
|
||||
```
|
||||
|
||||
### Usage with Jest
|
||||
|
||||
Logging with Jest is _problematic_, as the test framework requires no asynchronous operation to
|
||||
continue after the test has finished. The following is the only supported way to use this module
|
||||
with Jest:
|
||||
|
||||
```js
|
||||
import pino from 'pino'
|
||||
import pretty from 'pino-pretty'
|
||||
|
||||
test('test pino-pretty', () => {
|
||||
const logger = pino(pretty({ sync: true }));
|
||||
logger.info('Info');
|
||||
logger.error('Error');
|
||||
});
|
||||
```
|
||||
|
||||
### Handling non-serializable options
|
||||
|
||||
Using the new [pino v7+
|
||||
transports](https://getpino.io/#/docs/transports?id=v7-transports) not all
|
||||
options are serializable, for example if you want to use `messageFormat` as a
|
||||
function you will need to wrap `pino-pretty` in a custom module.
|
||||
|
||||
Executing `main.js` below will log a colorized `hello world` message using a
|
||||
custom function `messageFormat`:
|
||||
|
||||
```js
|
||||
// main.js
|
||||
const pino = require('pino')
|
||||
|
||||
const logger = pino({
|
||||
transport: {
|
||||
target: './pino-pretty-transport',
|
||||
options: {
|
||||
colorize: true
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
logger.info('world')
|
||||
```
|
||||
|
||||
```js
|
||||
// pino-pretty-transport.js
|
||||
module.exports = opts => require('pino-pretty')({
|
||||
...opts,
|
||||
messageFormat: (log, messageKey) => `hello ${log[messageKey]}`
|
||||
})
|
||||
```
|
||||
|
||||
### Checking color support in TTY
|
||||
|
||||
This boolean returns whether the currently used TTY supports colorizing the logs.
|
||||
|
||||
```js
|
||||
import pretty from 'pino-pretty'
|
||||
|
||||
if (pretty.isColorSupported) {
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
<a id="options"></a>
|
||||
### Options
|
||||
|
||||
The options accepted have keys corresponding to the options described in [CLI Arguments](#cliargs):
|
||||
|
||||
```js
|
||||
{
|
||||
colorize: colorette.isColorSupported, // --colorize
|
||||
colorizeObjects: true, //--colorizeObjects
|
||||
crlf: false, // --crlf
|
||||
errorLikeObjectKeys: ['err', 'error'], // --errorLikeObjectKeys (not required to match custom errorKey with pino >=8.21.0)
|
||||
errorProps: '', // --errorProps
|
||||
levelFirst: false, // --levelFirst
|
||||
messageKey: 'msg', // --messageKey (not required with pino >=8.21.0)
|
||||
levelKey: 'level', // --levelKey
|
||||
messageFormat: false, // --messageFormat
|
||||
timestampKey: 'time', // --timestampKey
|
||||
translateTime: false, // --translateTime
|
||||
ignore: 'pid,hostname', // --ignore
|
||||
include: 'level,time', // --include
|
||||
hideObject: false, // --hideObject
|
||||
singleLine: false, // --singleLine
|
||||
customColors: 'err:red,info:blue', // --customColors
|
||||
customLevels: 'err:99,info:1', // --customLevels (not required with pino >=8.21.0)
|
||||
levelLabel: 'levelLabel', // --levelLabel
|
||||
minimumLevel: 'info', // --minimumLevel
|
||||
useOnlyCustomProps: true, // --useOnlyCustomProps
|
||||
// The file or file descriptor (1 is stdout) to write to
|
||||
destination: 1,
|
||||
|
||||
// Alternatively, pass a `sonic-boom` instance (allowing more flexibility):
|
||||
// destination: new SonicBoom({ dest: 'a/file', mkdir: true })
|
||||
|
||||
// You can also configure some SonicBoom options directly
|
||||
sync: false, // by default we write asynchronously
|
||||
append: true, // the file is opened with the 'a' flag
|
||||
mkdir: true, // create the target destination
|
||||
|
||||
|
||||
customPrettifiers: {}
|
||||
}
|
||||
```
|
||||
|
||||
The `colorize` default follows
|
||||
[`colorette.isColorSupported`](https://github.com/jorgebucaran/colorette#iscolorsupported).
|
||||
|
||||
The defaults for `sync`, `append`, `mkdir` inherit from
|
||||
[`SonicBoom(opts)`](https://github.com/pinojs/sonic-boom#API).
|
||||
|
||||
`customPrettifiers` option provides the ability to add a custom prettify function
|
||||
for specific log properties. `customPrettifiers` is an object, where keys are
|
||||
log properties that will be prettified and value is the prettify function itself.
|
||||
For example, if a log line contains a `query` property,
|
||||
you can specify a prettifier for it:
|
||||
|
||||
```js
|
||||
{
|
||||
customPrettifiers: {
|
||||
query: prettifyQuery
|
||||
}
|
||||
}
|
||||
//...
|
||||
const prettifyQuery = value => {
|
||||
// do some prettify magic
|
||||
}
|
||||
```
|
||||
|
||||
All prettifiers use this function signature:
|
||||
|
||||
```js
|
||||
['logObjKey']: (output, keyName, logObj, extras) => string
|
||||
```
|
||||
|
||||
* `logObjKey` - name of the key of the property in the log object that should have this function applied to it
|
||||
* `output` - the value of the property in the log object
|
||||
* `keyName` - the name of the property (useful for `level` and `message` when `levelKey` or `messageKey` is used)
|
||||
* `logObj` - the full log object, for context
|
||||
* `extras` - an object containing **additional** data/functions created in the context of this pino-pretty logger or specific to the key (see `level` prettifying below)
|
||||
* All `extras` objects contain `colors` which is a [Colorette](https://github.com/jorgebucaran/colorette?tab=readme-ov-file#supported-colors) object containing color functions. Colors are enabled based on `colorize` provided to pino-pretty or `colorette.isColorSupported` if `colorize` was not provided.
|
||||
|
||||
Additionally, `customPrettifiers` can be used to format the `time`, `hostname`,
|
||||
`pid`, `name`, `caller` and `level` outputs AS WELL AS any arbitrary key-value that exists on a given log object.
|
||||
|
||||
An example usage of `customPrettifiers` using all parameters from the function signature:
|
||||
|
||||
```js
|
||||
{
|
||||
customPrettifiers: {
|
||||
// The argument for this function will be the same
|
||||
// string that's at the start of the log-line by default:
|
||||
time: timestamp => `🕰 ${timestamp}`,
|
||||
|
||||
// The argument for the level-prettifier may vary depending
|
||||
// on if the levelKey option is used or not.
|
||||
// By default this will be the same numerics as the Pino default:
|
||||
level: logLevel => `LEVEL: ${logLevel}`,
|
||||
// level provides additional data in `extras`:
|
||||
// * label => derived level label string
|
||||
// * labelColorized => derived level label string with colorette colors applied based on customColors and whether colors are supported
|
||||
level: (logLevel, key, log, { label, labelColorized, colors }) => `LEVEL: ${logLevel} LABEL: ${levelLabel} COLORIZED LABEL: ${labelColorized}`,
|
||||
|
||||
// other prettifiers can be used for the other keys if needed, for example
|
||||
hostname: hostname => `MY HOST: ${hostname}`,
|
||||
pid: pid => pid,
|
||||
name: (name, key, log, { colors }) => `${colors.blue(name)}`,
|
||||
caller: (caller, key, log, { colors }) => `${colors.greenBright(caller)}`,
|
||||
myCustomLogProp: (value, key, log, { colors }) => `My Prop -> ${colors.bold(value)} <--`
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`messageFormat` option allows you to customize the message output.
|
||||
A template `string` like this can define the format:
|
||||
|
||||
```js
|
||||
{
|
||||
messageFormat: '{levelLabel} - {pid} - url:{req.url}'
|
||||
}
|
||||
```
|
||||
|
||||
In addition to this, if / end statement blocks can also be specified.
|
||||
Else statements and nested conditions are not supported.
|
||||
|
||||
```js
|
||||
{
|
||||
messageFormat: '{levelLabel} - {if pid}{pid} - {end}url:{req.url}'
|
||||
}
|
||||
```
|
||||
|
||||
This option can also be defined as a `function` with this function signature:
|
||||
|
||||
```js
|
||||
{
|
||||
messageFormat: (log, messageKey, levelLabel, { colors }) => {
|
||||
// do some log message customization
|
||||
//
|
||||
// `colors` is a Colorette object with colors enabled based on `colorize` option
|
||||
return `This is a ${colors.red('colorized')}, custom message: ${log[messageKey]}`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
Because `pino-pretty` uses stdout redirection, in some cases the command may
|
||||
terminate with an error due to shell limitations.
|
||||
|
||||
For example, currently, mingw64 based shells (e.g. Bash as supplied by [git for
|
||||
Windows](https://gitforwindows.org)) are affected and terminate the process with
|
||||
a `stdout is not a tty` error message.
|
||||
|
||||
Any PRs are welcomed!
|
||||
|
||||
<a id="license"></a>
|
||||
## License
|
||||
|
||||
MIT License
|
||||
@@ -0,0 +1,38 @@
|
||||
// Code generated by Herebyfile.mjs generate:enums from internal/nodebuilder/types.go. DO NOT EDIT.
|
||||
export var NodeBuilderFlags;
|
||||
(function (NodeBuilderFlags) {
|
||||
NodeBuilderFlags[NodeBuilderFlags["None"] = 0] = "None";
|
||||
NodeBuilderFlags[NodeBuilderFlags["NoTruncation"] = 1] = "NoTruncation";
|
||||
NodeBuilderFlags[NodeBuilderFlags["WriteArrayAsGenericType"] = 2] = "WriteArrayAsGenericType";
|
||||
NodeBuilderFlags[NodeBuilderFlags["GenerateNamesForShadowedTypeParams"] = 4] = "GenerateNamesForShadowedTypeParams";
|
||||
NodeBuilderFlags[NodeBuilderFlags["UseStructuralFallback"] = 8] = "UseStructuralFallback";
|
||||
NodeBuilderFlags[NodeBuilderFlags["ForbidIndexedAccessSymbolReferences"] = 16] = "ForbidIndexedAccessSymbolReferences";
|
||||
NodeBuilderFlags[NodeBuilderFlags["WriteTypeArgumentsOfSignature"] = 32] = "WriteTypeArgumentsOfSignature";
|
||||
NodeBuilderFlags[NodeBuilderFlags["UseFullyQualifiedType"] = 64] = "UseFullyQualifiedType";
|
||||
NodeBuilderFlags[NodeBuilderFlags["UseOnlyExternalAliasing"] = 128] = "UseOnlyExternalAliasing";
|
||||
NodeBuilderFlags[NodeBuilderFlags["SuppressAnyReturnType"] = 256] = "SuppressAnyReturnType";
|
||||
NodeBuilderFlags[NodeBuilderFlags["WriteTypeParametersInQualifiedName"] = 512] = "WriteTypeParametersInQualifiedName";
|
||||
NodeBuilderFlags[NodeBuilderFlags["MultilineObjectLiterals"] = 1024] = "MultilineObjectLiterals";
|
||||
NodeBuilderFlags[NodeBuilderFlags["WriteClassExpressionAsTypeLiteral"] = 2048] = "WriteClassExpressionAsTypeLiteral";
|
||||
NodeBuilderFlags[NodeBuilderFlags["UseTypeOfFunction"] = 4096] = "UseTypeOfFunction";
|
||||
NodeBuilderFlags[NodeBuilderFlags["OmitParameterModifiers"] = 8192] = "OmitParameterModifiers";
|
||||
NodeBuilderFlags[NodeBuilderFlags["UseAliasDefinedOutsideCurrentScope"] = 16384] = "UseAliasDefinedOutsideCurrentScope";
|
||||
NodeBuilderFlags[NodeBuilderFlags["UseSingleQuotesForStringLiteralType"] = 268435456] = "UseSingleQuotesForStringLiteralType";
|
||||
NodeBuilderFlags[NodeBuilderFlags["NoTypeReduction"] = 536870912] = "NoTypeReduction";
|
||||
NodeBuilderFlags[NodeBuilderFlags["UseInstantiationExpressions"] = 1073741824] = "UseInstantiationExpressions";
|
||||
NodeBuilderFlags[NodeBuilderFlags["OmitThisParameter"] = 33554432] = "OmitThisParameter";
|
||||
NodeBuilderFlags[NodeBuilderFlags["WriteCallStyleSignature"] = 134217728] = "WriteCallStyleSignature";
|
||||
NodeBuilderFlags[NodeBuilderFlags["AllowThisInObjectLiteral"] = 32768] = "AllowThisInObjectLiteral";
|
||||
NodeBuilderFlags[NodeBuilderFlags["AllowQualifiedNameInPlaceOfIdentifier"] = 65536] = "AllowQualifiedNameInPlaceOfIdentifier";
|
||||
NodeBuilderFlags[NodeBuilderFlags["AllowAnonymousIdentifier"] = 131072] = "AllowAnonymousIdentifier";
|
||||
NodeBuilderFlags[NodeBuilderFlags["AllowEmptyUnionOrIntersection"] = 262144] = "AllowEmptyUnionOrIntersection";
|
||||
NodeBuilderFlags[NodeBuilderFlags["AllowEmptyTuple"] = 524288] = "AllowEmptyTuple";
|
||||
NodeBuilderFlags[NodeBuilderFlags["AllowUniqueESSymbolType"] = 1048576] = "AllowUniqueESSymbolType";
|
||||
NodeBuilderFlags[NodeBuilderFlags["AllowEmptyIndexInfoType"] = 2097152] = "AllowEmptyIndexInfoType";
|
||||
NodeBuilderFlags[NodeBuilderFlags["AllowNodeModulesRelativePaths"] = 67108864] = "AllowNodeModulesRelativePaths";
|
||||
NodeBuilderFlags[NodeBuilderFlags["IgnoreErrors"] = 70221824] = "IgnoreErrors";
|
||||
NodeBuilderFlags[NodeBuilderFlags["InObjectTypeLiteral"] = 4194304] = "InObjectTypeLiteral";
|
||||
NodeBuilderFlags[NodeBuilderFlags["InTypeAlias"] = 8388608] = "InTypeAlias";
|
||||
NodeBuilderFlags[NodeBuilderFlags["InInitialEntityName"] = 16777216] = "InInitialEntityName";
|
||||
})(NodeBuilderFlags || (NodeBuilderFlags = {}));
|
||||
//# sourceMappingURL=nodeBuilderFlags.enum.js.map
|
||||
@@ -0,0 +1,29 @@
|
||||
The encoding indexes, algorithms, and many comments in the code
|
||||
derive from the Encoding Standard https://encoding.spec.whatwg.org/
|
||||
|
||||
Otherwise...
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const es2023_intl: LibDefinition;
|
||||
@@ -0,0 +1,90 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SUPPORTED_TYPESCRIPT_VERSIONS = void 0;
|
||||
exports.handleUnsupportedTSVersion = handleUnsupportedTSVersion;
|
||||
const semver_1 = __importDefault(require("semver"));
|
||||
const ts = __importStar(require("typescript"));
|
||||
const version_1 = require("../version");
|
||||
/**
|
||||
* This needs to be kept in sync with package.json in the typescript-eslint monorepo
|
||||
*/
|
||||
exports.SUPPORTED_TYPESCRIPT_VERSIONS = '>=4.8.4 <6.1.0';
|
||||
/*
|
||||
* The semver package will ignore prerelease ranges, and we don't want to explicitly document every one
|
||||
* List them all separately here, so we can automatically create the full string
|
||||
*/
|
||||
const SUPPORTED_PRERELEASE_RANGES = [];
|
||||
const ACTIVE_TYPESCRIPT_VERSION = ts.version;
|
||||
const isRunningSupportedTypeScriptVersion = semver_1.default.satisfies(ACTIVE_TYPESCRIPT_VERSION, [exports.SUPPORTED_TYPESCRIPT_VERSIONS, ...SUPPORTED_PRERELEASE_RANGES].join(' || '));
|
||||
let warnedAboutTSVersion = false;
|
||||
function buildUnsupportedTSVersionMessage(severity) {
|
||||
const label = severity === 'error' ? 'ERROR' : 'WARNING';
|
||||
const border = '=============';
|
||||
return [
|
||||
border,
|
||||
'\n',
|
||||
`${label}: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.`,
|
||||
'\n',
|
||||
`* @typescript-eslint/typescript-estree version: ${version_1.version}`,
|
||||
`* Supported TypeScript versions: ${exports.SUPPORTED_TYPESCRIPT_VERSIONS}`,
|
||||
`* Your TypeScript version: ${ACTIVE_TYPESCRIPT_VERSION}`,
|
||||
'\n',
|
||||
'Please only submit bug reports when using the officially supported version.',
|
||||
'\n',
|
||||
border,
|
||||
].join('\n');
|
||||
}
|
||||
function handleUnsupportedTSVersion(parseSettings, behavior, passedLoggerFn) {
|
||||
if (isRunningSupportedTypeScriptVersion || behavior === 'ignore') {
|
||||
return;
|
||||
}
|
||||
if (behavior === 'error') {
|
||||
throw new Error(buildUnsupportedTSVersionMessage('error'));
|
||||
}
|
||||
if (warnedAboutTSVersion) {
|
||||
return;
|
||||
}
|
||||
if (passedLoggerFn ||
|
||||
// See https://github.com/typescript-eslint/typescript-eslint/issues/7896
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
(typeof process === 'undefined' ? false : process.stdout?.isTTY)) {
|
||||
parseSettings.log(buildUnsupportedTSVersionMessage('warn'));
|
||||
}
|
||||
warnedAboutTSVersion = true;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { ZodErrorMap } from "./ZodError.js";
|
||||
import defaultErrorMap from "./locales/en.js";
|
||||
export { defaultErrorMap };
|
||||
export declare function setErrorMap(map: ZodErrorMap): void;
|
||||
export declare function getErrorMap(): ZodErrorMap;
|
||||
@@ -0,0 +1,733 @@
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const os = require('node:os')
|
||||
const { join } = require('node:path')
|
||||
const { once } = require('node:events')
|
||||
const { setImmediate: immediate } = require('node:timers/promises')
|
||||
const { readFile, writeFile } = require('node:fs').promises
|
||||
const url = require('url')
|
||||
const strip = require('strip-ansi')
|
||||
const execa = require('execa')
|
||||
const writer = require('flush-write-stream')
|
||||
const rimraf = require('rimraf')
|
||||
const tspl = require('@matteo.collina/tspl')
|
||||
|
||||
const { match, watchFileCreated, watchForWrite, file } = require('../helper')
|
||||
const pino = require('../../')
|
||||
|
||||
const { tmpdir } = os
|
||||
const pid = process.pid
|
||||
const hostname = os.hostname()
|
||||
|
||||
test('pino.transport with file', async (t) => {
|
||||
const destination = file()
|
||||
const transport = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport with file (no options + error handling)', async () => {
|
||||
const transport = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js')
|
||||
})
|
||||
const [err] = await once(transport, 'error')
|
||||
assert.equal(err.message, 'kaboom')
|
||||
})
|
||||
|
||||
test('pino.transport with file URL', async (t) => {
|
||||
const destination = file()
|
||||
const transport = pino.transport({
|
||||
target: url.pathToFileURL(join(__dirname, '..', 'fixtures', 'to-file-transport.js')).href,
|
||||
options: { destination }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport errors if file does not exists', (t, end) => {
|
||||
const instance = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'non-existent-file'),
|
||||
worker: {
|
||||
stdin: true,
|
||||
stdout: true,
|
||||
stderr: true
|
||||
}
|
||||
})
|
||||
instance.on('error', function () {
|
||||
assert.ok('error received')
|
||||
end()
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport errors if transport worker module does not export a function', async (t) => {
|
||||
// TODO: add case for non-pipelined single target (needs changes in thread-stream)
|
||||
const plan = tspl(t, { plan: 2 })
|
||||
const manyTargetsInstance = pino.transport({
|
||||
targets: [{
|
||||
level: 'info',
|
||||
target: join(__dirname, '..', 'fixtures', 'transport-wrong-export-type.js')
|
||||
}, {
|
||||
level: 'info',
|
||||
target: join(__dirname, '..', 'fixtures', 'transport-wrong-export-type.js')
|
||||
}]
|
||||
})
|
||||
manyTargetsInstance.on('error', function (e) {
|
||||
plan.equal(e.message, 'exported worker is not a function')
|
||||
})
|
||||
|
||||
const pipelinedInstance = pino.transport({
|
||||
pipeline: [{
|
||||
target: join(__dirname, '..', 'fixtures', 'transport-wrong-export-type.js')
|
||||
}]
|
||||
})
|
||||
pipelinedInstance.on('error', function (e) {
|
||||
plan.equal(e.message, 'exported worker is not a function')
|
||||
})
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test('pino.transport with esm', async (t) => {
|
||||
const destination = file()
|
||||
const transport = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.mjs'),
|
||||
options: { destination }
|
||||
})
|
||||
const instance = pino(transport)
|
||||
t.after(transport.end.bind(transport))
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport with two files', async (t) => {
|
||||
const dest1 = file()
|
||||
const dest2 = file()
|
||||
const transport = pino.transport({
|
||||
targets: [{
|
||||
level: 'info',
|
||||
target: 'file://' + join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination: dest1 }
|
||||
}, {
|
||||
level: 'info',
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination: dest2 }
|
||||
}]
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await Promise.all([watchFileCreated(dest1), watchFileCreated(dest2)])
|
||||
const result1 = JSON.parse(await readFile(dest1))
|
||||
delete result1.time
|
||||
assert.deepEqual(result1, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
const result2 = JSON.parse(await readFile(dest2))
|
||||
delete result2.time
|
||||
assert.deepEqual(result2, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport with two files and custom levels', async (t) => {
|
||||
const dest1 = file()
|
||||
const dest2 = file()
|
||||
const transport = pino.transport({
|
||||
targets: [{
|
||||
level: 'info',
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination: dest1 }
|
||||
}, {
|
||||
level: 'foo',
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination: dest2 }
|
||||
}],
|
||||
levels: { trace: 10, debug: 20, info: 30, warn: 40, error: 50, fatal: 60, foo: 25 }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await Promise.all([watchFileCreated(dest1), watchFileCreated(dest2)])
|
||||
const result1 = JSON.parse(await readFile(dest1))
|
||||
delete result1.time
|
||||
assert.deepEqual(result1, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
const result2 = JSON.parse(await readFile(dest2))
|
||||
delete result2.time
|
||||
assert.deepEqual(result2, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport without specifying default levels', async (t) => {
|
||||
const dest = file()
|
||||
const transport = pino.transport({
|
||||
targets: [{
|
||||
level: 'foo',
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination: dest }
|
||||
}],
|
||||
levels: { foo: 25 }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await Promise.all([watchFileCreated(dest)])
|
||||
const result1 = JSON.parse(await readFile(dest))
|
||||
delete result1.time
|
||||
assert.deepEqual(result1, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport with two files and dedupe', async (t) => {
|
||||
const dest1 = file()
|
||||
const dest2 = file()
|
||||
const transport = pino.transport({
|
||||
dedupe: true,
|
||||
targets: [{
|
||||
level: 'info',
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination: dest1 }
|
||||
}, {
|
||||
level: 'error',
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination: dest2 }
|
||||
}]
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
instance.error('world')
|
||||
await Promise.all([watchFileCreated(dest1), watchFileCreated(dest2)])
|
||||
const result1 = JSON.parse(await readFile(dest1))
|
||||
delete result1.time
|
||||
assert.deepEqual(result1, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
const result2 = JSON.parse(await readFile(dest2))
|
||||
delete result2.time
|
||||
assert.deepEqual(result2, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 50,
|
||||
msg: 'world'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport with an array including a pino-pretty destination', async (t) => {
|
||||
const dest1 = file()
|
||||
const dest2 = file()
|
||||
const transport = pino.transport({
|
||||
targets: [{
|
||||
level: 'info',
|
||||
target: 'pino/file',
|
||||
options: {
|
||||
destination: dest1
|
||||
}
|
||||
}, {
|
||||
level: 'info',
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
destination: dest2
|
||||
}
|
||||
}]
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await Promise.all([watchFileCreated(dest1), watchFileCreated(dest2)])
|
||||
const result1 = JSON.parse(await readFile(dest1))
|
||||
delete result1.time
|
||||
assert.deepEqual(result1, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
const actual = (await readFile(dest2)).toString()
|
||||
assert.match(strip(actual), /\[.*\] INFO.*hello/)
|
||||
})
|
||||
|
||||
test('no transport.end()', async (t) => {
|
||||
const destination = file()
|
||||
const transport = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination }
|
||||
})
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('autoEnd = false', async (t) => {
|
||||
const destination = file()
|
||||
const count = process.listenerCount('exit')
|
||||
const transport = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
|
||||
options: { destination },
|
||||
worker: { autoEnd: false }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
await once(transport, 'ready')
|
||||
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
|
||||
await watchFileCreated(destination)
|
||||
|
||||
assert.equal(count, process.listenerCount('exit'))
|
||||
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport with target and targets', async () => {
|
||||
assert.throws(
|
||||
() => {
|
||||
pino.transport({
|
||||
target: '/a/file',
|
||||
targets: [{
|
||||
target: '/a/file'
|
||||
}]
|
||||
})
|
||||
},
|
||||
/only one of target or targets can be specified/
|
||||
)
|
||||
})
|
||||
|
||||
test('pino.transport with target pino/file', async (t) => {
|
||||
const destination = file()
|
||||
const transport = pino.transport({
|
||||
target: 'pino/file',
|
||||
options: { destination }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport with target pino/file and mkdir option', async (t) => {
|
||||
const folder = join(tmpdir(), `pino-${process.pid}-mkdir-transport-file`)
|
||||
const destination = join(folder, 'log.txt')
|
||||
t.after(() => {
|
||||
try {
|
||||
rimraf.sync(folder)
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
})
|
||||
const transport = pino.transport({
|
||||
target: 'pino/file',
|
||||
options: { destination, mkdir: true }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport with target pino/file and append option', async (t) => {
|
||||
const destination = file()
|
||||
await writeFile(destination, JSON.stringify({ pid, hostname, time: Date.now(), level: 30, msg: 'hello' }))
|
||||
const transport = pino.transport({
|
||||
target: 'pino/file',
|
||||
options: { destination, append: false }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('goodbye')
|
||||
await watchForWrite(destination, '"goodbye"')
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'goodbye'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino.transport should error with unknown target', async () => {
|
||||
assert.throws(
|
||||
() => {
|
||||
pino.transport({
|
||||
target: 'origin',
|
||||
caller: 'unknown-file.js'
|
||||
})
|
||||
},
|
||||
/unable to determine transport target for "origin"/
|
||||
)
|
||||
})
|
||||
|
||||
test('pino.transport with target pino-pretty', async (t) => {
|
||||
const destination = file()
|
||||
const transport = pino.transport({
|
||||
target: 'pino-pretty',
|
||||
options: { destination }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const actual = await readFile(destination, 'utf8')
|
||||
assert.match(strip(actual), /\[.*\] INFO.*hello/)
|
||||
})
|
||||
|
||||
test('sets worker data informing the transport that pino will send its config', async (t) => {
|
||||
const plan = tspl(t, { plan: 1 })
|
||||
const transport = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'transport-worker-data.js')
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
transport.once('workerData', (workerData) => {
|
||||
match(workerData.workerData, { pinoWillSendConfig: true })
|
||||
plan.ok('passed')
|
||||
})
|
||||
instance.info('hello')
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test('sets worker data informing the transport that pino will send its config (frozen file)', async (t) => {
|
||||
const plan = tspl(t, { plan: 1 })
|
||||
const config = {
|
||||
transport: {
|
||||
target: join(__dirname, '..', 'fixtures', 'transport-worker-data.js'),
|
||||
options: {}
|
||||
}
|
||||
}
|
||||
Object.freeze(config)
|
||||
Object.freeze(config.transport)
|
||||
Object.freeze(config.transport.options)
|
||||
const instance = pino(config)
|
||||
const transport = instance[pino.symbols.streamSym]
|
||||
t.after(transport.end.bind(transport))
|
||||
transport.once('workerData', (workerData) => {
|
||||
match(workerData.workerData, { pinoWillSendConfig: true })
|
||||
plan.ok('passed')
|
||||
})
|
||||
instance.info('hello')
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test('stdout in worker', async () => {
|
||||
let actual = ''
|
||||
const child = execa(process.argv[0], [join(__dirname, '..', 'fixtures', 'transport-main.js')])
|
||||
|
||||
for await (const chunk of child.stdout) {
|
||||
actual += chunk
|
||||
}
|
||||
assert.equal(strip(actual).match(/Hello/) != null, true)
|
||||
})
|
||||
|
||||
test('log and exit on ready', async () => {
|
||||
let actual = ''
|
||||
const child = execa(process.argv[0], [join(__dirname, '..', 'fixtures', 'transport-exit-on-ready.js')])
|
||||
|
||||
child.stdout.pipe(writer((s, enc, cb) => {
|
||||
actual += s
|
||||
cb()
|
||||
}))
|
||||
await once(child, 'close')
|
||||
await immediate()
|
||||
assert.equal(strip(actual).match(/Hello/) != null, true)
|
||||
})
|
||||
|
||||
test('log and exit before ready', async () => {
|
||||
let actual = ''
|
||||
const child = execa(process.argv[0], [join(__dirname, '..', 'fixtures', 'transport-exit-immediately.js')])
|
||||
|
||||
child.stdout.pipe(writer((s, enc, cb) => {
|
||||
actual += s
|
||||
cb()
|
||||
}))
|
||||
await once(child, 'close')
|
||||
await immediate()
|
||||
assert.equal(strip(actual).match(/Hello/) != null, true)
|
||||
})
|
||||
|
||||
test('log and exit before ready with async dest', async () => {
|
||||
const destination = file()
|
||||
const child = execa(process.argv[0], [join(__dirname, '..', 'fixtures', 'transport-exit-immediately-with-async-dest.js'), destination])
|
||||
|
||||
await once(child, 'exit')
|
||||
|
||||
const actual = await readFile(destination, 'utf8')
|
||||
assert.equal(strip(actual).match(/HELLO/) != null, true)
|
||||
assert.equal(strip(actual).match(/WORLD/) != null, true)
|
||||
})
|
||||
|
||||
test('string integer destination', async () => {
|
||||
let actual = ''
|
||||
const child = execa(process.argv[0], [join(__dirname, '..', 'fixtures', 'transport-string-stdout.js')])
|
||||
|
||||
child.stdout.pipe(writer((s, enc, cb) => {
|
||||
actual += s
|
||||
cb()
|
||||
}))
|
||||
await once(child, 'close')
|
||||
await immediate()
|
||||
assert.equal(strip(actual).match(/Hello/) != null, true)
|
||||
})
|
||||
|
||||
test('pino transport options with target', async (t) => {
|
||||
const destination = file()
|
||||
const instance = pino({
|
||||
transport: {
|
||||
target: 'pino/file',
|
||||
options: { destination }
|
||||
}
|
||||
})
|
||||
const transportStream = instance[pino.symbols.streamSym]
|
||||
t.after(transportStream.end.bind(transportStream))
|
||||
instance.info('transport option test')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'transport option test'
|
||||
})
|
||||
})
|
||||
|
||||
test('pino transport options with targets', async (t) => {
|
||||
const dest1 = file()
|
||||
const dest2 = file()
|
||||
const instance = pino({
|
||||
transport: {
|
||||
targets: [
|
||||
{ target: 'pino/file', options: { destination: dest1 } },
|
||||
{ target: 'pino/file', options: { destination: dest2 } }
|
||||
]
|
||||
}
|
||||
})
|
||||
const transportStream = instance[pino.symbols.streamSym]
|
||||
t.after(transportStream.end.bind(transportStream))
|
||||
instance.info('transport option test')
|
||||
|
||||
await Promise.all([watchFileCreated(dest1), watchFileCreated(dest2)])
|
||||
const result1 = JSON.parse(await readFile(dest1))
|
||||
delete result1.time
|
||||
assert.deepEqual(result1, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'transport option test'
|
||||
})
|
||||
const result2 = JSON.parse(await readFile(dest2))
|
||||
delete result2.time
|
||||
assert.deepEqual(result2, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'transport option test'
|
||||
})
|
||||
})
|
||||
|
||||
test('transport options with target and targets', async () => {
|
||||
assert.throws(
|
||||
() => {
|
||||
pino({
|
||||
transport: {
|
||||
target: {},
|
||||
targets: {}
|
||||
}
|
||||
})
|
||||
},
|
||||
/only one of target or targets can be specified/
|
||||
)
|
||||
})
|
||||
|
||||
test('transport options with target and stream', async () => {
|
||||
assert.throws(
|
||||
() => {
|
||||
pino({
|
||||
transport: {
|
||||
target: {}
|
||||
}
|
||||
}, '/log/null')
|
||||
},
|
||||
/only one of option.transport or stream can be specified/
|
||||
)
|
||||
})
|
||||
|
||||
test('transport options with stream', async (t) => {
|
||||
const dest1 = file()
|
||||
const transportStream = pino.transport({ target: 'pino/file', options: { destination: dest1 } })
|
||||
t.after(transportStream.end.bind(transportStream))
|
||||
assert.throws(
|
||||
() => {
|
||||
pino({
|
||||
transport: transportStream
|
||||
})
|
||||
},
|
||||
Error('option.transport do not allow stream, please pass to option directly. e.g. pino(transport)')
|
||||
)
|
||||
})
|
||||
|
||||
test('pino.transport handles prototype pollution of __bundlerPathsOverrides', async (t) => {
|
||||
// eslint-disable-next-line no-extend-native
|
||||
Object.prototype.__bundlerPathsOverrides = { 'pino/file': '/malicious/path' }
|
||||
t.after(() => {
|
||||
delete Object.prototype.__bundlerPathsOverrides
|
||||
})
|
||||
|
||||
const destination = file()
|
||||
const transport = pino.transport({
|
||||
target: 'pino/file',
|
||||
options: { destination }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
const hasThreadName = 'threadName' in require('worker_threads')
|
||||
|
||||
test('pino.transport with single target sets worker thread name to target', { skip: !hasThreadName }, async (t) => {
|
||||
const plan = tspl(t, { plan: 1 })
|
||||
const transport = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'transport-worker-name.js')
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
transport.once('workerThreadName', (name) => {
|
||||
plan.equal(name, join(__dirname, '..', 'fixtures', 'transport-worker-name.js'))
|
||||
})
|
||||
instance.info('hello')
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test('pino.transport with targets sets worker thread name to pino.transport', { skip: !hasThreadName }, async (t) => {
|
||||
const plan = tspl(t, { plan: 1 })
|
||||
const transport = pino.transport({
|
||||
targets: [{
|
||||
level: 'info',
|
||||
target: join(__dirname, '..', 'fixtures', 'transport-worker-name.js')
|
||||
}]
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
transport.once('workerThreadName', (name) => {
|
||||
plan.equal(name, 'pino.transport')
|
||||
})
|
||||
instance.info('hello')
|
||||
|
||||
await plan
|
||||
})
|
||||
|
||||
test('pino.transport with pipeline sets worker thread name to pino.transport', { skip: !hasThreadName }, async (t) => {
|
||||
const plan = tspl(t, { plan: 1 })
|
||||
const transport = pino.transport({
|
||||
pipeline: [{
|
||||
target: join(__dirname, '..', 'fixtures', 'transport-worker-name.js')
|
||||
}]
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
transport.once('workerThreadName', (name) => {
|
||||
plan.equal(name, 'pino.transport')
|
||||
})
|
||||
instance.info('hello')
|
||||
|
||||
await plan
|
||||
})
|
||||
@@ -0,0 +1,114 @@
|
||||
import type * as core from "../core/index.js";
|
||||
import type * as JSONSchema from "./json-schema.js";
|
||||
import { type $ZodRegistry } from "./registries.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import type { StandardJSONSchemaV1, StandardSchemaWithJSONProps } from "./standard-schema.js";
|
||||
export type Processor<T extends schemas.$ZodType = schemas.$ZodType> = (schema: T, ctx: ToJSONSchemaContext, json: JSONSchema.BaseSchema, params: ProcessParams) => void;
|
||||
export interface JSONSchemaGeneratorParams {
|
||||
processors: Record<string, Processor>;
|
||||
/** A registry used to look up metadata for each schema. Any schema with an `id` property will be extracted as a $def.
|
||||
* @default globalRegistry */
|
||||
metadata?: $ZodRegistry<Record<string, any>>;
|
||||
/** The JSON Schema version to target.
|
||||
* - `"draft-2020-12"` — Default. JSON Schema Draft 2020-12
|
||||
* - `"draft-07"` — JSON Schema Draft 7
|
||||
* - `"draft-04"` — JSON Schema Draft 4
|
||||
* - `"openapi-3.0"` — OpenAPI 3.0 Schema Object */
|
||||
target?: "draft-04" | "draft-07" | "draft-2020-12" | "openapi-3.0" | ({} & string) | undefined;
|
||||
/** How to handle unrepresentable types.
|
||||
* - `"throw"` — Default. Unrepresentable types throw an error
|
||||
* - `"any"` — Unrepresentable types become `{}` */
|
||||
unrepresentable?: "throw" | "any";
|
||||
/** Arbitrary custom logic that can be used to modify the generated JSON Schema. */
|
||||
override?: (ctx: {
|
||||
zodSchema: schemas.$ZodTypes;
|
||||
jsonSchema: JSONSchema.BaseSchema;
|
||||
path: (string | number)[];
|
||||
}) => void;
|
||||
/** Whether to extract the `"input"` or `"output"` type. Relevant to transforms, defaults, coerced primitives, etc.
|
||||
* - `"output"` — Default. Convert the output schema.
|
||||
* - `"input"` — Convert the input schema. */
|
||||
io?: "input" | "output";
|
||||
cycles?: "ref" | "throw";
|
||||
reused?: "ref" | "inline";
|
||||
external?: {
|
||||
registry: $ZodRegistry<{
|
||||
id?: string | undefined;
|
||||
}>;
|
||||
uri?: ((id: string) => string) | undefined;
|
||||
defs: Record<string, JSONSchema.BaseSchema>;
|
||||
} | undefined;
|
||||
}
|
||||
/**
|
||||
* Parameters for the toJSONSchema function.
|
||||
*/
|
||||
export type ToJSONSchemaParams = Omit<JSONSchemaGeneratorParams, "processors" | "external">;
|
||||
/**
|
||||
* Parameters for the toJSONSchema function when passing a registry.
|
||||
*/
|
||||
export interface RegistryToJSONSchemaParams extends ToJSONSchemaParams {
|
||||
uri?: (id: string) => string;
|
||||
}
|
||||
export interface ProcessParams {
|
||||
schemaPath: schemas.$ZodType[];
|
||||
path: (string | number)[];
|
||||
}
|
||||
export interface Seen {
|
||||
/** JSON Schema result for this Zod schema */
|
||||
schema: JSONSchema.BaseSchema;
|
||||
/** A cached version of the schema that doesn't get overwritten during ref resolution */
|
||||
def?: JSONSchema.BaseSchema;
|
||||
defId?: string | undefined;
|
||||
/** Number of times this schema was encountered during traversal */
|
||||
count: number;
|
||||
/** Cycle path */
|
||||
cycle?: (string | number)[] | undefined;
|
||||
isParent?: boolean | undefined;
|
||||
/** Schema to inherit JSON Schema properties from (set by processor for wrappers) */
|
||||
ref?: schemas.$ZodType | null;
|
||||
/** JSON Schema property path for this schema */
|
||||
path?: (string | number)[] | undefined;
|
||||
}
|
||||
export interface ToJSONSchemaContext {
|
||||
processors: Record<string, Processor>;
|
||||
metadataRegistry: $ZodRegistry<Record<string, any>>;
|
||||
target: "draft-04" | "draft-07" | "draft-2020-12" | "openapi-3.0" | ({} & string);
|
||||
unrepresentable: "throw" | "any";
|
||||
override: (ctx: {
|
||||
zodSchema: schemas.$ZodType;
|
||||
jsonSchema: JSONSchema.BaseSchema;
|
||||
path: (string | number)[];
|
||||
}) => void;
|
||||
io: "input" | "output";
|
||||
counter: number;
|
||||
seen: Map<schemas.$ZodType, Seen>;
|
||||
cycles: "ref" | "throw";
|
||||
reused: "ref" | "inline";
|
||||
external?: {
|
||||
registry: $ZodRegistry<{
|
||||
id?: string | undefined;
|
||||
}>;
|
||||
uri?: ((id: string) => string) | undefined;
|
||||
defs: Record<string, JSONSchema.BaseSchema>;
|
||||
} | undefined;
|
||||
}
|
||||
export declare function initializeContext(params: JSONSchemaGeneratorParams): ToJSONSchemaContext;
|
||||
export declare function process<T extends schemas.$ZodType>(schema: T, ctx: ToJSONSchemaContext, _params?: ProcessParams): JSONSchema.BaseSchema;
|
||||
export declare function extractDefs<T extends schemas.$ZodType>(ctx: ToJSONSchemaContext, schema: T): void;
|
||||
export declare function finalize<T extends schemas.$ZodType>(ctx: ToJSONSchemaContext, schema: T): ZodStandardJSONSchemaPayload<T>;
|
||||
export type ZodStandardSchemaWithJSON<T> = StandardSchemaWithJSONProps<core.input<T>, core.output<T>>;
|
||||
export interface ZodStandardJSONSchemaPayload<T> extends JSONSchema.BaseSchema {
|
||||
"~standard": ZodStandardSchemaWithJSON<T>;
|
||||
}
|
||||
/**
|
||||
* Creates a toJSONSchema method for a schema instance.
|
||||
* This encapsulates the logic of initializing context, processing, extracting defs, and finalizing.
|
||||
*/
|
||||
export declare const createToJSONSchemaMethod: <T extends schemas.$ZodType>(schema: T, processors?: Record<string, Processor>) => (params?: ToJSONSchemaParams) => ZodStandardJSONSchemaPayload<T>;
|
||||
/**
|
||||
* Creates a toJSONSchema method for a schema instance.
|
||||
* This encapsulates the logic of initializing context, processing, extracting defs, and finalizing.
|
||||
*/
|
||||
type StandardJSONSchemaMethodParams = Parameters<StandardJSONSchemaV1["~standard"]["jsonSchema"]["input"]>[0];
|
||||
export declare const createStandardJSONSchemaMethod: <T extends schemas.$ZodType>(schema: T, io: "input" | "output", processors?: Record<string, Processor>) => (params?: StandardJSONSchemaMethodParams) => JSONSchema.BaseSchema;
|
||||
export {};
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"bn254.d.ts","sourceRoot":"","sources":["src/bn254.ts"],"names":[],"mappings":"AAyDA,OAAO,EAEL,KAAK,OAAO,IAAI,UAAU,EAC1B,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAS,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG3D,OAAO,EAAE,KAAK,OAAO,EAAqC,MAAM,2BAA2B,CAAC;AAsB5F,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,CAA2B,CAAC;AAsDhE,eAAO,MAAM,eAAe,EAAE,gBAY7B,CAAC;AAmBF;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,UAgDlB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAS9B,CAAC"}
|
||||
@@ -0,0 +1,7 @@
|
||||
import _typeof from "./typeof.js";
|
||||
import toPrimitive from "./toPrimitive.js";
|
||||
function toPropertyKey(t) {
|
||||
var i = toPrimitive(t, "string");
|
||||
return "symbol" == _typeof(i) ? i : i + "";
|
||||
}
|
||||
export { toPropertyKey as default };
|
||||
@@ -0,0 +1,41 @@
|
||||
# stackback
|
||||
|
||||
Returns an array of CallSite objects for a captured stacktrace. Useful if you want to access the frame for an error object.
|
||||
|
||||
## use
|
||||
|
||||
```javascript
|
||||
var stackback = require('stackback');
|
||||
|
||||
// error generated from somewhere
|
||||
var err = new Error('some sample error');
|
||||
|
||||
// stack is an array of CallSite objects
|
||||
var stack = stackback(err);
|
||||
```
|
||||
|
||||
## CallSite object
|
||||
|
||||
From the [V8 StackTrace API](https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi)
|
||||
|
||||
The structured stack trace is an Array of CallSite objects, each of which represents a stack frame. A CallSite object defines the following methods
|
||||
|
||||
getThis: returns the value of this
|
||||
getTypeName: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object's [[Class]] internal property.
|
||||
getFunction: returns the current function
|
||||
getFunctionName: returns the name of the current function, typically its name property. If a name property is not available an attempt will be made to try to infer a name from the function's context.
|
||||
getMethodName: returns the name of the property of this or one of its prototypes that holds the current function
|
||||
getFileName: if this function was defined in a script returns the name of the script
|
||||
getLineNumber: if this function was defined in a script returns the current line number
|
||||
getColumnNumber: if this function was defined in a script returns the current column number
|
||||
getEvalOrigin: if this function was created using a call to eval returns a CallSite object representing the location where eval was called
|
||||
isToplevel: is this a toplevel invocation, that is, is this the global object?
|
||||
isEval: does this call take place in code defined by a call to eval?
|
||||
isNative: is this call in native V8 code?
|
||||
isConstructor: is this a constructor call?
|
||||
|
||||
## install
|
||||
|
||||
```shell
|
||||
npm install stackback
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
// See LICENSE.md for more information.
|
||||
|
||||
import {
|
||||
TextDecoder as TextDecoderPolyfill,
|
||||
TextEncoder as TextEncoderPolyfill,
|
||||
} from './encoding.js'
|
||||
|
||||
function getGlobal() {
|
||||
if (typeof self !== 'undefined') return self;
|
||||
if (typeof global !== 'undefined') return global;
|
||||
throw new Error('No global found');
|
||||
}
|
||||
|
||||
if (typeof TextDecoder !== 'function') {
|
||||
getGlobal().TextDecoder = TextDecoderPolyfill;
|
||||
}
|
||||
|
||||
if (typeof TextEncoder !== 'function') {
|
||||
getGlobal().TextEncoder = TextEncoderPolyfill;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import set from "./set.js";
|
||||
import getPrototypeOf from "./getPrototypeOf.js";
|
||||
function _superPropSet(t, e, o, r, p, f) {
|
||||
return set(getPrototypeOf(f ? t.prototype : t), e, o, r, p);
|
||||
}
|
||||
export { _superPropSet as default };
|
||||
@@ -0,0 +1,121 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getEnumLiterals = getEnumLiterals;
|
||||
exports.getEnumTypes = getEnumTypes;
|
||||
exports.getEnumKeyForLiteral = getEnumKeyForLiteral;
|
||||
const tsutils = __importStar(require("ts-api-utils"));
|
||||
const ts = __importStar(require("typescript"));
|
||||
const util_1 = require("../../util");
|
||||
/*
|
||||
* If passed an enum member, returns the type of the parent. Otherwise,
|
||||
* returns itself.
|
||||
*
|
||||
* For example:
|
||||
* - `Fruit` --> `Fruit`
|
||||
* - `Fruit.Apple` --> `Fruit`
|
||||
*/
|
||||
function getBaseEnumType(typeChecker, type) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const symbol = type.getSymbol();
|
||||
if (!tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) {
|
||||
return type;
|
||||
}
|
||||
return typeChecker.getTypeAtLocation(symbol.valueDeclaration.parent);
|
||||
}
|
||||
/**
|
||||
* Retrieve only the Enum literals from a type. for example:
|
||||
* - 123 --> []
|
||||
* - {} --> []
|
||||
* - Fruit.Apple --> [Fruit.Apple]
|
||||
* - Fruit.Apple | Vegetable.Lettuce --> [Fruit.Apple, Vegetable.Lettuce]
|
||||
* - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit.Apple, Vegetable.Lettuce]
|
||||
* - T extends Fruit --> [Fruit]
|
||||
*/
|
||||
function getEnumLiterals(type) {
|
||||
return tsutils
|
||||
.unionConstituents(type)
|
||||
.filter((subType) => (0, util_1.isTypeFlagSet)(subType, ts.TypeFlags.EnumLiteral));
|
||||
}
|
||||
/**
|
||||
* A type can have 0 or more enum types. For example:
|
||||
* - 123 --> []
|
||||
* - {} --> []
|
||||
* - Fruit.Apple --> [Fruit]
|
||||
* - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable]
|
||||
* - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable]
|
||||
* - T extends Fruit --> [Fruit]
|
||||
*/
|
||||
function getEnumTypes(typeChecker, type) {
|
||||
return getEnumLiterals(type).map(type => getBaseEnumType(typeChecker, type));
|
||||
}
|
||||
/**
|
||||
* Returns the enum key that matches the given literal node, or null if none
|
||||
* match. For example:
|
||||
* ```ts
|
||||
* enum Fruit {
|
||||
* Apple = 'apple',
|
||||
* Banana = 'banana',
|
||||
* }
|
||||
*
|
||||
* getEnumKeyForLiteral([Fruit.Apple, Fruit.Banana], 'apple') --> 'Fruit.Apple'
|
||||
* getEnumKeyForLiteral([Fruit.Apple, Fruit.Banana], 'banana') --> 'Fruit.Banana'
|
||||
* getEnumKeyForLiteral([Fruit.Apple, Fruit.Banana], 'cherry') --> null
|
||||
* ```
|
||||
*/
|
||||
function getEnumKeyForLiteral(enumLiterals, literal) {
|
||||
for (const enumLiteral of enumLiterals) {
|
||||
if (enumLiteral.value === literal) {
|
||||
const { symbol } = enumLiteral;
|
||||
const memberDeclaration = symbol.valueDeclaration;
|
||||
const enumDeclaration = memberDeclaration.parent;
|
||||
const memberNameIdentifier = memberDeclaration.name;
|
||||
const enumName = enumDeclaration.name.text;
|
||||
switch (memberNameIdentifier.kind) {
|
||||
case ts.SyntaxKind.Identifier:
|
||||
return `${enumName}.${memberNameIdentifier.text}`;
|
||||
case ts.SyntaxKind.StringLiteral: {
|
||||
const memberName = memberNameIdentifier.text.replaceAll("'", "\\'");
|
||||
return `${enumName}['${memberName}']`;
|
||||
}
|
||||
case ts.SyntaxKind.ComputedPropertyName:
|
||||
return `${enumName}[${memberNameIdentifier.expression.getText()}]`;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user