WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
'use strict'
|
||||
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const util = require('util')
|
||||
const utils = require('../utils')
|
||||
|
||||
const NativeQuery = (module.exports = function (config, values, callback) {
|
||||
EventEmitter.call(this)
|
||||
config = utils.normalizeQueryConfig(config, values, callback)
|
||||
this.text = config.text
|
||||
this.values = config.values
|
||||
this.name = config.name
|
||||
this.queryMode = config.queryMode
|
||||
this.callback = config.callback
|
||||
this.state = 'new'
|
||||
this._arrayMode = config.rowMode === 'array'
|
||||
|
||||
// if the 'row' event is listened for
|
||||
// then emit them as they come in
|
||||
// without setting singleRowMode to true
|
||||
// this has almost no meaning because libpq
|
||||
// reads all rows into memory before returning any
|
||||
this._emitRowEvents = false
|
||||
this.on(
|
||||
'newListener',
|
||||
function (event) {
|
||||
if (event === 'row') this._emitRowEvents = true
|
||||
}.bind(this)
|
||||
)
|
||||
})
|
||||
|
||||
util.inherits(NativeQuery, EventEmitter)
|
||||
|
||||
const errorFieldMap = {
|
||||
sqlState: 'code',
|
||||
statementPosition: 'position',
|
||||
messagePrimary: 'message',
|
||||
context: 'where',
|
||||
schemaName: 'schema',
|
||||
tableName: 'table',
|
||||
columnName: 'column',
|
||||
dataTypeName: 'dataType',
|
||||
constraintName: 'constraint',
|
||||
sourceFile: 'file',
|
||||
sourceLine: 'line',
|
||||
sourceFunction: 'routine',
|
||||
}
|
||||
|
||||
NativeQuery.prototype.handleError = function (err) {
|
||||
// copy pq error fields into the error object
|
||||
const fields = this.native && this.native.pq.resultErrorFields()
|
||||
if (fields) {
|
||||
for (const key in fields) {
|
||||
const normalizedFieldName = errorFieldMap[key] || key
|
||||
err[normalizedFieldName] = fields[key]
|
||||
}
|
||||
}
|
||||
if (this.callback) {
|
||||
this.callback(err)
|
||||
} else {
|
||||
this.emit('error', err)
|
||||
}
|
||||
this.state = 'error'
|
||||
}
|
||||
|
||||
NativeQuery.prototype.then = function (onSuccess, onFailure) {
|
||||
return this._getPromise().then(onSuccess, onFailure)
|
||||
}
|
||||
|
||||
NativeQuery.prototype.catch = function (callback) {
|
||||
return this._getPromise().catch(callback)
|
||||
}
|
||||
|
||||
NativeQuery.prototype._getPromise = function () {
|
||||
if (this._promise) return this._promise
|
||||
this._promise = new Promise(
|
||||
function (resolve, reject) {
|
||||
this._once('end', resolve)
|
||||
this._once('error', reject)
|
||||
}.bind(this)
|
||||
)
|
||||
return this._promise
|
||||
}
|
||||
|
||||
NativeQuery.prototype.submit = function (client) {
|
||||
this.state = 'running'
|
||||
const self = this
|
||||
this.native = client.native
|
||||
client.native.arrayMode = this._arrayMode
|
||||
|
||||
let after = function (err, rows, results) {
|
||||
client.native.arrayMode = false
|
||||
setImmediate(function () {
|
||||
self.emit('_done')
|
||||
})
|
||||
|
||||
// handle possible query error
|
||||
if (err) {
|
||||
return self.handleError(err)
|
||||
}
|
||||
|
||||
// emit row events for each row in the result
|
||||
if (self._emitRowEvents) {
|
||||
if (results.length > 1) {
|
||||
rows.forEach((rowOfRows, i) => {
|
||||
rowOfRows.forEach((row) => {
|
||||
self.emit('row', row, results[i])
|
||||
})
|
||||
})
|
||||
} else {
|
||||
rows.forEach(function (row) {
|
||||
self.emit('row', row, results)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// handle successful result
|
||||
self.state = 'end'
|
||||
self.emit('end', results)
|
||||
if (self.callback) {
|
||||
self.callback(null, results)
|
||||
}
|
||||
}
|
||||
|
||||
if (process.domain) {
|
||||
after = process.domain.bind(after)
|
||||
}
|
||||
|
||||
// named query
|
||||
if (this.name) {
|
||||
if (this.name.length > 63) {
|
||||
console.error('Warning! Postgres only supports 63 characters for query names.')
|
||||
console.error('You supplied %s (%s)', this.name, this.name.length)
|
||||
console.error('This can cause conflicts and silent errors executing queries')
|
||||
}
|
||||
const values = (this.values || []).map(utils.prepareValue)
|
||||
|
||||
// check if the client has already executed this named query
|
||||
// if so...just execute it again - skip the planning phase
|
||||
if (client.namedQueries[this.name]) {
|
||||
if (this.text && client.namedQueries[this.name] !== this.text) {
|
||||
const err = new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`)
|
||||
return after(err)
|
||||
}
|
||||
return client.native.execute(this.name, values, after)
|
||||
}
|
||||
// plan the named query the first time, then execute it
|
||||
return client.native.prepare(this.name, this.text, values.length, function (err) {
|
||||
if (err) return after(err)
|
||||
client.namedQueries[self.name] = self.text
|
||||
return self.native.execute(self.name, values, after)
|
||||
})
|
||||
} else if (this.values) {
|
||||
if (!Array.isArray(this.values)) {
|
||||
const err = new Error('Query values must be an array')
|
||||
return after(err)
|
||||
}
|
||||
const vals = this.values.map(utils.prepareValue)
|
||||
client.native.query(this.text, vals, after)
|
||||
} else if (this.queryMode === 'extended') {
|
||||
client.native.query(this.text, [], after)
|
||||
} else {
|
||||
client.native.query(this.text, after)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,508 @@
|
||||
declare module "node:readline" {
|
||||
import { Abortable, EventEmitter, InternalEventEmitter } from "node:events";
|
||||
interface Key {
|
||||
sequence?: string | undefined;
|
||||
name?: string | undefined;
|
||||
ctrl?: boolean | undefined;
|
||||
meta?: boolean | undefined;
|
||||
shift?: boolean | undefined;
|
||||
}
|
||||
interface InterfaceEventMap {
|
||||
"close": [];
|
||||
"error": [error: Error];
|
||||
"history": [history: string[]];
|
||||
"line": [input: string];
|
||||
"pause": [];
|
||||
"resume": [];
|
||||
"SIGCONT": [];
|
||||
"SIGINT": [];
|
||||
"SIGTSTP": [];
|
||||
}
|
||||
/**
|
||||
* Instances of the `readline.Interface` class are constructed using the `readline.createInterface()` method. Every instance is associated with a
|
||||
* single `input` [Readable](https://nodejs.org/docs/latest-v26.x/api/stream.html#readable-streams) stream and a single `output` [Writable](https://nodejs.org/docs/latest-v26.x/api/stream.html#writable-streams) stream.
|
||||
* The `output` stream is used to print prompts for user input that arrives on,
|
||||
* and is read from, the `input` stream.
|
||||
* @since v0.1.104
|
||||
*/
|
||||
class Interface implements EventEmitter, Disposable {
|
||||
/**
|
||||
* NOTE: According to the documentation:
|
||||
*
|
||||
* > Instances of the `readline.Interface` class are constructed using the
|
||||
* > `readline.createInterface()` method.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v26.x/docs/api/readline.html#class-interfaceconstructor
|
||||
*/
|
||||
protected constructor(
|
||||
input: NodeJS.ReadableStream,
|
||||
output?: NodeJS.WritableStream,
|
||||
completer?: Completer | AsyncCompleter,
|
||||
terminal?: boolean,
|
||||
);
|
||||
/**
|
||||
* NOTE: According to the documentation:
|
||||
*
|
||||
* > Instances of the `readline.Interface` class are constructed using the
|
||||
* > `readline.createInterface()` method.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v26.x/docs/api/readline.html#class-interfaceconstructor
|
||||
*/
|
||||
protected constructor(options: ReadLineOptions);
|
||||
readonly terminal: boolean;
|
||||
/**
|
||||
* The current input data being processed by node.
|
||||
*
|
||||
* This can be used when collecting input from a TTY stream to retrieve the
|
||||
* current value that has been processed thus far, prior to the `line` event
|
||||
* being emitted. Once the `line` event has been emitted, this property will
|
||||
* be an empty string.
|
||||
*
|
||||
* Be aware that modifying the value during the instance runtime may have
|
||||
* unintended consequences if `rl.cursor` is not also controlled.
|
||||
*
|
||||
* **If not using a TTY stream for input, use the `'line'` event.**
|
||||
*
|
||||
* One possible use case would be as follows:
|
||||
*
|
||||
* ```js
|
||||
* const values = ['lorem ipsum', 'dolor sit amet'];
|
||||
* const rl = readline.createInterface(process.stdin);
|
||||
* const showResults = debounce(() => {
|
||||
* console.log(
|
||||
* '\n',
|
||||
* values.filter((val) => val.startsWith(rl.line)).join(' '),
|
||||
* );
|
||||
* }, 300);
|
||||
* process.stdin.on('keypress', (c, k) => {
|
||||
* showResults();
|
||||
* });
|
||||
* ```
|
||||
* @since v0.1.98
|
||||
*/
|
||||
readonly line: string;
|
||||
/**
|
||||
* The cursor position relative to `rl.line`.
|
||||
*
|
||||
* This will track where the current cursor lands in the input string, when
|
||||
* reading input from a TTY stream. The position of cursor determines the
|
||||
* portion of the input string that will be modified as input is processed,
|
||||
* as well as the column where the terminal caret will be rendered.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
readonly cursor: number;
|
||||
/**
|
||||
* The `rl.getPrompt()` method returns the current prompt used by `rl.prompt()`.
|
||||
* @since v15.3.0, v14.17.0
|
||||
* @return the current prompt string
|
||||
*/
|
||||
getPrompt(): string;
|
||||
/**
|
||||
* The `rl.setPrompt()` method sets the prompt that will be written to `output` whenever `rl.prompt()` is called.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
setPrompt(prompt: string): void;
|
||||
/**
|
||||
* The `rl.prompt()` method writes the `Interface` instances configured`prompt` to a new line in `output` in order to provide a user with a new
|
||||
* location at which to provide input.
|
||||
*
|
||||
* When called, `rl.prompt()` will resume the `input` stream if it has been
|
||||
* paused.
|
||||
*
|
||||
* If the `Interface` was created with `output` set to `null` or `undefined` the prompt is not written.
|
||||
* @since v0.1.98
|
||||
* @param preserveCursor If `true`, prevents the cursor placement from being reset to `0`.
|
||||
*/
|
||||
prompt(preserveCursor?: boolean): void;
|
||||
/**
|
||||
* The `rl.question()` method displays the `query` by writing it to the `output`,
|
||||
* waits for user input to be provided on `input`, then invokes the `callback` function passing the provided input as the first argument.
|
||||
*
|
||||
* When called, `rl.question()` will resume the `input` stream if it has been
|
||||
* paused.
|
||||
*
|
||||
* If the `Interface` was created with `output` set to `null` or `undefined` the `query` is not written.
|
||||
*
|
||||
* The `callback` function passed to `rl.question()` does not follow the typical
|
||||
* pattern of accepting an `Error` object or `null` as the first argument.
|
||||
* The `callback` is called with the provided answer as the only argument.
|
||||
*
|
||||
* An error will be thrown if calling `rl.question()` after `rl.close()`.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ```js
|
||||
* rl.question('What is your favorite food? ', (answer) => {
|
||||
* console.log(`Oh, so your favorite food is ${answer}`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Using an `AbortController` to cancel a question.
|
||||
*
|
||||
* ```js
|
||||
* const ac = new AbortController();
|
||||
* const signal = ac.signal;
|
||||
*
|
||||
* rl.question('What is your favorite food? ', { signal }, (answer) => {
|
||||
* console.log(`Oh, so your favorite food is ${answer}`);
|
||||
* });
|
||||
*
|
||||
* signal.addEventListener('abort', () => {
|
||||
* console.log('The food question timed out');
|
||||
* }, { once: true });
|
||||
*
|
||||
* setTimeout(() => ac.abort(), 10000);
|
||||
* ```
|
||||
* @since v0.3.3
|
||||
* @param query A statement or query to write to `output`, prepended to the prompt.
|
||||
* @param callback A callback function that is invoked with the user's input in response to the `query`.
|
||||
*/
|
||||
question(query: string, callback: (answer: string) => void): void;
|
||||
question(query: string, options: Abortable, callback: (answer: string) => void): void;
|
||||
/**
|
||||
* The `rl.pause()` method pauses the `input` stream, allowing it to be resumed
|
||||
* later if necessary.
|
||||
*
|
||||
* Calling `rl.pause()` does not immediately pause other events (including `'line'`) from being emitted by the `Interface` instance.
|
||||
* @since v0.3.4
|
||||
*/
|
||||
pause(): this;
|
||||
/**
|
||||
* The `rl.resume()` method resumes the `input` stream if it has been paused.
|
||||
* @since v0.3.4
|
||||
*/
|
||||
resume(): this;
|
||||
/**
|
||||
* The `rl.close()` method closes the `Interface` instance and
|
||||
* relinquishes control over the `input` and `output` streams. When called,
|
||||
* the `'close'` event will be emitted.
|
||||
*
|
||||
* Calling `rl.close()` does not immediately stop other events (including `'line'`)
|
||||
* from being emitted by the `Interface` instance.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
close(): void;
|
||||
/**
|
||||
* Alias for `rl.close()`.
|
||||
* @since v22.15.0
|
||||
*/
|
||||
[Symbol.dispose](): void;
|
||||
/**
|
||||
* The `rl.write()` method will write either `data` or a key sequence identified
|
||||
* by `key` to the `output`. The `key` argument is supported only if `output` is
|
||||
* a `TTY` text terminal. See `TTY keybindings` for a list of key
|
||||
* combinations.
|
||||
*
|
||||
* If `key` is specified, `data` is ignored.
|
||||
*
|
||||
* When called, `rl.write()` will resume the `input` stream if it has been
|
||||
* paused.
|
||||
*
|
||||
* If the `Interface` was created with `output` set to `null` or `undefined` the `data` and `key` are not written.
|
||||
*
|
||||
* ```js
|
||||
* rl.write('Delete this!');
|
||||
* // Simulate Ctrl+U to delete the line written previously
|
||||
* rl.write(null, { ctrl: true, name: 'u' });
|
||||
* ```
|
||||
*
|
||||
* The `rl.write()` method will write the data to the `readline` `Interface`'s `input` _as if it were provided by the user_.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
write(data: string | Buffer, key?: Key): void;
|
||||
write(data: undefined | null | string | Buffer, key: Key): void;
|
||||
/**
|
||||
* Returns the real position of the cursor in relation to the input
|
||||
* prompt + string. Long input (wrapping) strings, as well as multiple
|
||||
* line prompts are included in the calculations.
|
||||
* @since v13.5.0, v12.16.0
|
||||
*/
|
||||
getCursorPos(): CursorPos;
|
||||
[Symbol.asyncIterator](): NodeJS.AsyncIterator<string>;
|
||||
}
|
||||
interface Interface extends InternalEventEmitter<InterfaceEventMap> {}
|
||||
type Completer = (line: string) => CompleterResult;
|
||||
type AsyncCompleter = (
|
||||
line: string,
|
||||
callback: (err?: null | Error, result?: CompleterResult) => void,
|
||||
) => void;
|
||||
type CompleterResult = [string[], string];
|
||||
interface ReadLineOptions {
|
||||
/**
|
||||
* The [`Readable`](https://nodejs.org/docs/latest-v26.x/api/stream.html#readable-streams) stream to listen to
|
||||
*/
|
||||
input: NodeJS.ReadableStream;
|
||||
/**
|
||||
* The [`Writable`](https://nodejs.org/docs/latest-v26.x/api/stream.html#writable-streams) stream to write readline data to.
|
||||
*/
|
||||
output?: NodeJS.WritableStream | undefined;
|
||||
/**
|
||||
* An optional function used for Tab autocompletion.
|
||||
*/
|
||||
completer?: Completer | AsyncCompleter | undefined;
|
||||
/**
|
||||
* `true` if the `input` and `output` streams should be treated like a TTY,
|
||||
* and have ANSI/VT100 escape codes written to it.
|
||||
* Default: checking `isTTY` on the `output` stream upon instantiation.
|
||||
*/
|
||||
terminal?: boolean | undefined;
|
||||
/**
|
||||
* Initial list of history lines.
|
||||
* This option makes sense only if `terminal` is set to `true` by the user or by an internal `output` check,
|
||||
* otherwise the history caching mechanism is not initialized at all.
|
||||
* @default []
|
||||
*/
|
||||
history?: string[] | undefined;
|
||||
/**
|
||||
* Maximum number of history lines retained.
|
||||
* To disable the history set this value to `0`.
|
||||
* This option makes sense only if `terminal` is set to `true` by the user or by an internal `output` check,
|
||||
* otherwise the history caching mechanism is not initialized at all.
|
||||
* @default 30
|
||||
*/
|
||||
historySize?: number | undefined;
|
||||
/**
|
||||
* If `true`, when a new input line added to the history list duplicates an older one,
|
||||
* this removes the older line from the list.
|
||||
* @default false
|
||||
*/
|
||||
removeHistoryDuplicates?: boolean | undefined;
|
||||
/**
|
||||
* The prompt string to use.
|
||||
* @default "> "
|
||||
*/
|
||||
prompt?: string | undefined;
|
||||
/**
|
||||
* If the delay between `\r` and `\n` exceeds `crlfDelay` milliseconds,
|
||||
* both `\r` and `\n` will be treated as separate end-of-line input.
|
||||
* `crlfDelay` will be coerced to a number no less than `100`.
|
||||
* It can be set to `Infinity`, in which case
|
||||
* `\r` followed by `\n` will always be considered a single newline
|
||||
* (which may be reasonable for [reading files](https://nodejs.org/docs/latest-v26.x/api/readline.html#example-read-file-stream-line-by-line) with `\r\n` line delimiter).
|
||||
* @default 100
|
||||
*/
|
||||
crlfDelay?: number | undefined;
|
||||
/**
|
||||
* The duration `readline` will wait for a character
|
||||
* (when reading an ambiguous key sequence in milliseconds
|
||||
* one that can both form a complete key sequence using the input read so far
|
||||
* and can take additional input to complete a longer key sequence).
|
||||
* @default 500
|
||||
*/
|
||||
escapeCodeTimeout?: number | undefined;
|
||||
/**
|
||||
* The number of spaces a tab is equal to (minimum 1).
|
||||
* @default 8
|
||||
*/
|
||||
tabSize?: number | undefined;
|
||||
/**
|
||||
* Allows closing the interface using an AbortSignal.
|
||||
* Aborting the signal will internally call `close` on the interface.
|
||||
*/
|
||||
signal?: AbortSignal | undefined;
|
||||
}
|
||||
/**
|
||||
* The `readline.createInterface()` method creates a new `readline.Interface` instance.
|
||||
*
|
||||
* ```js
|
||||
* import readline from 'node:readline';
|
||||
* const rl = readline.createInterface({
|
||||
* input: process.stdin,
|
||||
* output: process.stdout,
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Once the `readline.Interface` instance is created, the most common case is to
|
||||
* listen for the `'line'` event:
|
||||
*
|
||||
* ```js
|
||||
* rl.on('line', (line) => {
|
||||
* console.log(`Received: ${line}`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* If `terminal` is `true` for this instance then the `output` stream will get
|
||||
* the best compatibility if it defines an `output.columns` property and emits
|
||||
* a `'resize'` event on the `output` if or when the columns ever change
|
||||
* (`process.stdout` does this automatically when it is a TTY).
|
||||
*
|
||||
* When creating a `readline.Interface` using `stdin` as input, the program
|
||||
* will not terminate until it receives an [EOF character](https://en.wikipedia.org/wiki/End-of-file#EOF_character). To exit without
|
||||
* waiting for user input, call `process.stdin.unref()`.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
function createInterface(
|
||||
input: NodeJS.ReadableStream,
|
||||
output?: NodeJS.WritableStream,
|
||||
completer?: Completer | AsyncCompleter,
|
||||
terminal?: boolean,
|
||||
): Interface;
|
||||
function createInterface(options: ReadLineOptions): Interface;
|
||||
/**
|
||||
* The `readline.emitKeypressEvents()` method causes the given `Readable` stream to begin emitting `'keypress'` events corresponding to received input.
|
||||
*
|
||||
* Optionally, `interface` specifies a `readline.Interface` instance for which
|
||||
* autocompletion is disabled when copy-pasted input is detected.
|
||||
*
|
||||
* If the `stream` is a `TTY`, then it must be in raw mode.
|
||||
*
|
||||
* This is automatically called by any readline instance on its `input` if the `input` is a terminal. Closing the `readline` instance does not stop
|
||||
* the `input` from emitting `'keypress'` events.
|
||||
*
|
||||
* ```js
|
||||
* readline.emitKeypressEvents(process.stdin);
|
||||
* if (process.stdin.isTTY)
|
||||
* process.stdin.setRawMode(true);
|
||||
* ```
|
||||
*
|
||||
* ## Example: Tiny CLI
|
||||
*
|
||||
* The following example illustrates the use of `readline.Interface` class to
|
||||
* implement a small command-line interface:
|
||||
*
|
||||
* ```js
|
||||
* import readline from 'node:readline';
|
||||
* const rl = readline.createInterface({
|
||||
* input: process.stdin,
|
||||
* output: process.stdout,
|
||||
* prompt: 'OHAI> ',
|
||||
* });
|
||||
*
|
||||
* rl.prompt();
|
||||
*
|
||||
* rl.on('line', (line) => {
|
||||
* switch (line.trim()) {
|
||||
* case 'hello':
|
||||
* console.log('world!');
|
||||
* break;
|
||||
* default:
|
||||
* console.log(`Say what? I might have heard '${line.trim()}'`);
|
||||
* break;
|
||||
* }
|
||||
* rl.prompt();
|
||||
* }).on('close', () => {
|
||||
* console.log('Have a great day!');
|
||||
* process.exit(0);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* ## Example: Read file stream line-by-Line
|
||||
*
|
||||
* A common use case for `readline` is to consume an input file one line at a
|
||||
* time. The easiest way to do so is leveraging the `fs.ReadStream` API as
|
||||
* well as a `for await...of` loop:
|
||||
*
|
||||
* ```js
|
||||
* import fs from 'node:fs';
|
||||
* import readline from 'node:readline';
|
||||
*
|
||||
* async function processLineByLine() {
|
||||
* const fileStream = fs.createReadStream('input.txt');
|
||||
*
|
||||
* const rl = readline.createInterface({
|
||||
* input: fileStream,
|
||||
* crlfDelay: Infinity,
|
||||
* });
|
||||
* // Note: we use the crlfDelay option to recognize all instances of CR LF
|
||||
* // ('\r\n') in input.txt as a single line break.
|
||||
*
|
||||
* for await (const line of rl) {
|
||||
* // Each line in input.txt will be successively available here as `line`.
|
||||
* console.log(`Line from file: ${line}`);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* processLineByLine();
|
||||
* ```
|
||||
*
|
||||
* Alternatively, one could use the `'line'` event:
|
||||
*
|
||||
* ```js
|
||||
* import fs from 'node:fs';
|
||||
* import readline from 'node:readline';
|
||||
*
|
||||
* const rl = readline.createInterface({
|
||||
* input: fs.createReadStream('sample.txt'),
|
||||
* crlfDelay: Infinity,
|
||||
* });
|
||||
*
|
||||
* rl.on('line', (line) => {
|
||||
* console.log(`Line from file: ${line}`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Currently, `for await...of` loop can be a bit slower. If `async` / `await` flow and speed are both essential, a mixed approach can be applied:
|
||||
*
|
||||
* ```js
|
||||
* import { once } from 'node:events';
|
||||
* import { createReadStream } from 'node:fs';
|
||||
* import { createInterface } from 'node:readline';
|
||||
*
|
||||
* (async function processLineByLine() {
|
||||
* try {
|
||||
* const rl = createInterface({
|
||||
* input: createReadStream('big-file.txt'),
|
||||
* crlfDelay: Infinity,
|
||||
* });
|
||||
*
|
||||
* rl.on('line', (line) => {
|
||||
* // Process the line.
|
||||
* });
|
||||
*
|
||||
* await once(rl, 'close');
|
||||
*
|
||||
* console.log('File processed.');
|
||||
* } catch (err) {
|
||||
* console.error(err);
|
||||
* }
|
||||
* })();
|
||||
* ```
|
||||
* @since v0.7.7
|
||||
*/
|
||||
function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void;
|
||||
type Direction = -1 | 0 | 1;
|
||||
interface CursorPos {
|
||||
rows: number;
|
||||
cols: number;
|
||||
}
|
||||
/**
|
||||
* The `readline.clearLine()` method clears current line of given [TTY](https://nodejs.org/docs/latest-v26.x/api/tty.html) stream
|
||||
* in a specified direction identified by `dir`.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean;
|
||||
/**
|
||||
* The `readline.clearScreenDown()` method clears the given [TTY](https://nodejs.org/docs/latest-v26.x/api/tty.html) stream from
|
||||
* the current position of the cursor down.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean;
|
||||
/**
|
||||
* The `readline.cursorTo()` method moves cursor to the specified position in a
|
||||
* given [TTY](https://nodejs.org/docs/latest-v26.x/api/tty.html) `stream`.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean;
|
||||
/**
|
||||
* The `readline.moveCursor()` method moves the cursor _relative_ to its current
|
||||
* position in a given [TTY](https://nodejs.org/docs/latest-v26.x/api/tty.html) `stream`.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean;
|
||||
/** @deprecated This alias will be removed in a future version. Use `import { Interface } from 'node:readline'` instead. */
|
||||
type ReadLine = Interface;
|
||||
}
|
||||
declare module "node:readline" {
|
||||
export * as promises from "node:readline/promises";
|
||||
}
|
||||
declare module "readline" {
|
||||
export * from "node:readline";
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
|
||||
const file2 = require("./file2.js")
|
||||
|
||||
module.exports = function () {
|
||||
file2()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { TSESLint } from '@typescript-eslint/utils';
|
||||
declare const _default: TSESLint.RuleModule<"noNonNullAssertedNullishCoalescing" | "suggestRemovingNonNull", [], import("../../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,34 @@
|
||||
import * as core from "../core/index.js";
|
||||
import * as schemas from "./schemas.js";
|
||||
export const ZodMiniISODateTime = /*@__PURE__*/ core.$constructor("ZodMiniISODateTime", (inst, def) => {
|
||||
core.$ZodISODateTime.init(inst, def);
|
||||
schemas.ZodMiniStringFormat.init(inst, def);
|
||||
});
|
||||
// @__NO_SIDE_EFFECTS__
|
||||
export function datetime(params) {
|
||||
return core._isoDateTime(ZodMiniISODateTime, params);
|
||||
}
|
||||
export const ZodMiniISODate = /*@__PURE__*/ core.$constructor("ZodMiniISODate", (inst, def) => {
|
||||
core.$ZodISODate.init(inst, def);
|
||||
schemas.ZodMiniStringFormat.init(inst, def);
|
||||
});
|
||||
// @__NO_SIDE_EFFECTS__
|
||||
export function date(params) {
|
||||
return core._isoDate(ZodMiniISODate, params);
|
||||
}
|
||||
export const ZodMiniISOTime = /*@__PURE__*/ core.$constructor("ZodMiniISOTime", (inst, def) => {
|
||||
core.$ZodISOTime.init(inst, def);
|
||||
schemas.ZodMiniStringFormat.init(inst, def);
|
||||
});
|
||||
// @__NO_SIDE_EFFECTS__
|
||||
export function time(params) {
|
||||
return core._isoTime(ZodMiniISOTime, params);
|
||||
}
|
||||
export const ZodMiniISODuration = /*@__PURE__*/ core.$constructor("ZodMiniISODuration", (inst, def) => {
|
||||
core.$ZodISODuration.init(inst, def);
|
||||
schemas.ZodMiniStringFormat.init(inst, def);
|
||||
});
|
||||
// @__NO_SIDE_EFFECTS__
|
||||
export function duration(params) {
|
||||
return core._isoDuration(ZodMiniISODuration, params);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
var _typeof = require("./typeof.js")["default"];
|
||||
var toPrimitive = require("./toPrimitive.js");
|
||||
function toPropertyKey(t) {
|
||||
var i = toPrimitive(t, "string");
|
||||
return "symbol" == _typeof(i) ? i : i + "";
|
||||
}
|
||||
module.exports = toPropertyKey, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,114 @@
|
||||
"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 });
|
||||
const tsutils = __importStar(require("ts-api-utils"));
|
||||
const util_1 = require("../util");
|
||||
exports.default = (0, util_1.createRule)({
|
||||
name: 'prefer-reduce-type-parameter',
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Enforce using type parameter when calling `Array#reduce` instead of using a type assertion',
|
||||
recommended: 'strict',
|
||||
requiresTypeChecking: true,
|
||||
},
|
||||
fixable: 'code',
|
||||
messages: {
|
||||
preferTypeParameter: 'Unnecessary assertion: Array#reduce accepts a type parameter for the default value.',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
create(context) {
|
||||
const services = (0, util_1.getParserServices)(context);
|
||||
const checker = services.program.getTypeChecker();
|
||||
function isArrayType(type) {
|
||||
return tsutils
|
||||
.unionConstituents(type)
|
||||
.every(unionPart => tsutils
|
||||
.intersectionConstituents(unionPart)
|
||||
.every(t => checker.isArrayType(t) || checker.isTupleType(t)));
|
||||
}
|
||||
return {
|
||||
'CallExpression > MemberExpression.callee'(callee) {
|
||||
if (!(0, util_1.isStaticMemberAccessOfValue)(callee, context, 'reduce')) {
|
||||
return;
|
||||
}
|
||||
const [, secondArg] = callee.parent.arguments;
|
||||
if (callee.parent.arguments.length < 2) {
|
||||
return;
|
||||
}
|
||||
if ((0, util_1.isTypeAssertion)(secondArg)) {
|
||||
const initializerType = services.getTypeAtLocation(secondArg.expression);
|
||||
const assertedType = services.getTypeAtLocation(secondArg.typeAnnotation);
|
||||
const isAssertionNecessary = !checker.isTypeAssignableTo(initializerType, assertedType);
|
||||
// don't report this if the resulting fix will be a type error
|
||||
if (isAssertionNecessary) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
// Get the symbol of the `reduce` method.
|
||||
const calleeObjType = (0, util_1.getConstrainedTypeAtLocation)(services, callee.object);
|
||||
// Check the owner type of the `reduce` method.
|
||||
if (isArrayType(calleeObjType)) {
|
||||
context.report({
|
||||
node: secondArg,
|
||||
messageId: 'preferTypeParameter',
|
||||
fix: fixer => {
|
||||
const fixes = [
|
||||
fixer.removeRange([
|
||||
secondArg.range[0],
|
||||
secondArg.expression.range[0],
|
||||
]),
|
||||
fixer.removeRange([
|
||||
secondArg.expression.range[1],
|
||||
secondArg.range[1],
|
||||
]),
|
||||
];
|
||||
if (!callee.parent.typeArguments) {
|
||||
fixes.push(fixer.insertTextAfter(callee, `<${context.sourceCode.getText(secondArg.typeAnnotation)}>`));
|
||||
}
|
||||
return fixes;
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
export declare class BufferReader {
|
||||
private offset;
|
||||
private buffer;
|
||||
private encoding;
|
||||
constructor(offset?: number);
|
||||
setBuffer(offset: number, buffer: Buffer): void;
|
||||
int16(): number;
|
||||
byte(): number;
|
||||
int32(): number;
|
||||
uint32(): number;
|
||||
string(length: number): string;
|
||||
cstring(): string;
|
||||
bytes(length: number): Buffer;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/ast/ast.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EACR,SAAS,EACT,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,SAAS,EACT,cAAc,EACd,KAAK,EACR,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,cAAc,oBAAoB,CAAC;AAInC,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG;IAAE,WAAW,EAAE,GAAG,CAAC;CAAE,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG;IAAE,mBAAmB,EAAE,IAAI,CAAC;CAAE,CAAC,GAAG,kBAAkB,CAAC;AAEtF,MAAM,WAAW,SAAS;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,IAAI,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC,EAAE,iBAAiB;IAClF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,IAAK,SAAQ,iBAAiB;IAC3C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,IAAI,EAAE,GAAG,SAAS,CAAC;IAC7C,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IACvG,aAAa,IAAI,UAAU,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,mBAAmB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzE,YAAY,IAAI,MAAM,CAAC;IACvB,MAAM,IAAI,MAAM,CAAC;IACjB,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1C,YAAY,IAAI,MAAM,CAAC;IACvB,qBAAqB,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IACvD,WAAW,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC7C,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;CAC5C;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC7B,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI;IACpC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,UAAU,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC1C,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,SAAS,aAAa,EAAE,CAAC;IACnD,QAAQ,CAAC,uBAAuB,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3D,QAAQ,CAAC,sBAAsB,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1D,QAAQ,CAAC,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;IAClC,QAAQ,CAAC,mBAAmB,EAAE,SAAS,IAAI,EAAE,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,uBAAuB,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1D,qEAAqE;IACrE,aAAa,IAAI,SAAS,MAAM,EAAE,CAAC;IACnC,8EAA8E;IAC9E,6BAA6B,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAClE,8EAA8E;IAC9E,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACvE,gBAAgB;IAChB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAClC;AAID,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,qBAAqB,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;AACjF,MAAM,MAAM,YAAY,CAAC,KAAK,SAAS,iBAAiB,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;AACzE,MAAM,MAAM,aAAa,CAAC,KAAK,SAAS,kBAAkB,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;AAIlF,MAAM,WAAW,kCAAmC,SAAQ,wBAAwB;IAChF,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC7B;AAED,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,kCAAkC,CAAC;AACnF,MAAM,MAAM,gCAAgC,GAAG,UAAU,GAAG,oBAAoB,CAAC;AAEjF,MAAM,WAAW,wBAAyB,SAAQ,wBAAwB;IACtE,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,cAAc,GAAG,wBAAwB,CAAC;CAC/E"}
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2021 = void 0;
|
||||
const es2020_1 = require("./es2020");
|
||||
const es2021_intl_1 = require("./es2021.intl");
|
||||
const es2021_promise_1 = require("./es2021.promise");
|
||||
const es2021_string_1 = require("./es2021.string");
|
||||
const es2021_weakref_1 = require("./es2021.weakref");
|
||||
exports.es2021 = {
|
||||
libs: [es2020_1.es2020, es2021_promise_1.es2021_promise, es2021_string_1.es2021_string, es2021_weakref_1.es2021_weakref, es2021_intl_1.es2021_intl],
|
||||
variables: [],
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
function _identity(t) {
|
||||
return t;
|
||||
}
|
||||
module.exports = _identity, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,7 @@
|
||||
import REGEX from './regex.js';
|
||||
|
||||
function validate(uuid) {
|
||||
return typeof uuid === 'string' && REGEX.test(uuid);
|
||||
}
|
||||
|
||||
export default validate;
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_async_generator.cjs",
|
||||
"module": "../../esm/_async_generator.js"
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
var test = require('tape');
|
||||
var stringify = require('../');
|
||||
|
||||
test('space parameter', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { one: 1, two: 2 };
|
||||
t.equal(stringify(obj, {space: ' '}), ''
|
||||
+ '{\n'
|
||||
+ ' "one": 1,\n'
|
||||
+ ' "two": 2\n'
|
||||
+ '}'
|
||||
);
|
||||
});
|
||||
|
||||
test('space parameter (with tabs)', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { one: 1, two: 2 };
|
||||
t.equal(stringify(obj, {space: '\t'}), ''
|
||||
+ '{\n'
|
||||
+ '\t"one": 1,\n'
|
||||
+ '\t"two": 2\n'
|
||||
+ '}'
|
||||
);
|
||||
});
|
||||
|
||||
test('space parameter (with a number)', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { one: 1, two: 2 };
|
||||
t.equal(stringify(obj, {space: 3}), ''
|
||||
+ '{\n'
|
||||
+ ' "one": 1,\n'
|
||||
+ ' "two": 2\n'
|
||||
+ '}'
|
||||
);
|
||||
});
|
||||
|
||||
test('space parameter (nested objects)', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { one: 1, two: { b: 4, a: [2,3] } };
|
||||
t.equal(stringify(obj, {space: ' '}), ''
|
||||
+ '{\n'
|
||||
+ ' "one": 1,\n'
|
||||
+ ' "two": {\n'
|
||||
+ ' "a": [\n'
|
||||
+ ' 2,\n'
|
||||
+ ' 3\n'
|
||||
+ ' ],\n'
|
||||
+ ' "b": 4\n'
|
||||
+ ' }\n'
|
||||
+ '}'
|
||||
);
|
||||
});
|
||||
|
||||
test('space parameter (same as native)', function (t) {
|
||||
t.plan(1);
|
||||
// for this test, properties need to be in alphabetical order
|
||||
var obj = { one: 1, two: { a: [2,3], b: 4 } };
|
||||
t.equal(stringify(obj, {space: ' '}), JSON.stringify(obj, null, ' '));
|
||||
});
|
||||
@@ -0,0 +1,313 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Utilities for hex, bytes, CSPRNG.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.wrapXOFConstructorWithOpts = exports.wrapConstructorWithOpts = exports.wrapConstructor = exports.Hash = exports.nextTick = exports.swap32IfBE = exports.byteSwapIfBE = exports.swap8IfBE = exports.isLE = void 0;
|
||||
exports.isBytes = isBytes;
|
||||
exports.anumber = anumber;
|
||||
exports.abytes = abytes;
|
||||
exports.ahash = ahash;
|
||||
exports.aexists = aexists;
|
||||
exports.aoutput = aoutput;
|
||||
exports.u8 = u8;
|
||||
exports.u32 = u32;
|
||||
exports.clean = clean;
|
||||
exports.createView = createView;
|
||||
exports.rotr = rotr;
|
||||
exports.rotl = rotl;
|
||||
exports.byteSwap = byteSwap;
|
||||
exports.byteSwap32 = byteSwap32;
|
||||
exports.bytesToHex = bytesToHex;
|
||||
exports.hexToBytes = hexToBytes;
|
||||
exports.asyncLoop = asyncLoop;
|
||||
exports.utf8ToBytes = utf8ToBytes;
|
||||
exports.bytesToUtf8 = bytesToUtf8;
|
||||
exports.toBytes = toBytes;
|
||||
exports.kdfInputToBytes = kdfInputToBytes;
|
||||
exports.concatBytes = concatBytes;
|
||||
exports.checkOpts = checkOpts;
|
||||
exports.createHasher = createHasher;
|
||||
exports.createOptHasher = createOptHasher;
|
||||
exports.createXOFer = createXOFer;
|
||||
exports.randomBytes = randomBytes;
|
||||
// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
|
||||
// node.js versions earlier than v19 don't declare it in global scope.
|
||||
// For node.js, package.json#exports field mapping rewrites import
|
||||
// from `crypto` to `cryptoNode`, which imports native module.
|
||||
// Makes the utils un-importable in browsers without a bundler.
|
||||
// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.
|
||||
const crypto_1 = require("@noble/hashes/crypto");
|
||||
/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */
|
||||
function isBytes(a) {
|
||||
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
||||
}
|
||||
/** Asserts something is positive integer. */
|
||||
function anumber(n) {
|
||||
if (!Number.isSafeInteger(n) || n < 0)
|
||||
throw new Error('positive integer expected, got ' + n);
|
||||
}
|
||||
/** Asserts something is Uint8Array. */
|
||||
function abytes(b, ...lengths) {
|
||||
if (!isBytes(b))
|
||||
throw new Error('Uint8Array expected');
|
||||
if (lengths.length > 0 && !lengths.includes(b.length))
|
||||
throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
|
||||
}
|
||||
/** Asserts something is hash */
|
||||
function ahash(h) {
|
||||
if (typeof h !== 'function' || typeof h.create !== 'function')
|
||||
throw new Error('Hash should be wrapped by utils.createHasher');
|
||||
anumber(h.outputLen);
|
||||
anumber(h.blockLen);
|
||||
}
|
||||
/** Asserts a hash instance has not been destroyed / finished */
|
||||
function aexists(instance, checkFinished = true) {
|
||||
if (instance.destroyed)
|
||||
throw new Error('Hash instance has been destroyed');
|
||||
if (checkFinished && instance.finished)
|
||||
throw new Error('Hash#digest() has already been called');
|
||||
}
|
||||
/** Asserts output is properly-sized byte array */
|
||||
function aoutput(out, instance) {
|
||||
abytes(out);
|
||||
const min = instance.outputLen;
|
||||
if (out.length < min) {
|
||||
throw new Error('digestInto() expects output buffer of length at least ' + min);
|
||||
}
|
||||
}
|
||||
/** Cast u8 / u16 / u32 to u8. */
|
||||
function u8(arr) {
|
||||
return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
||||
}
|
||||
/** Cast u8 / u16 / u32 to u32. */
|
||||
function u32(arr) {
|
||||
return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
|
||||
}
|
||||
/** Zeroize a byte array. Warning: JS provides no guarantees. */
|
||||
function clean(...arrays) {
|
||||
for (let i = 0; i < arrays.length; i++) {
|
||||
arrays[i].fill(0);
|
||||
}
|
||||
}
|
||||
/** Create DataView of an array for easy byte-level manipulation. */
|
||||
function createView(arr) {
|
||||
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
||||
}
|
||||
/** The rotate right (circular right shift) operation for uint32 */
|
||||
function rotr(word, shift) {
|
||||
return (word << (32 - shift)) | (word >>> shift);
|
||||
}
|
||||
/** The rotate left (circular left shift) operation for uint32 */
|
||||
function rotl(word, shift) {
|
||||
return (word << shift) | ((word >>> (32 - shift)) >>> 0);
|
||||
}
|
||||
/** Is current platform little-endian? Most are. Big-Endian platform: IBM */
|
||||
exports.isLE = (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();
|
||||
/** The byte swap operation for uint32 */
|
||||
function byteSwap(word) {
|
||||
return (((word << 24) & 0xff000000) |
|
||||
((word << 8) & 0xff0000) |
|
||||
((word >>> 8) & 0xff00) |
|
||||
((word >>> 24) & 0xff));
|
||||
}
|
||||
/** Conditionally byte swap if on a big-endian platform */
|
||||
exports.swap8IfBE = exports.isLE
|
||||
? (n) => n
|
||||
: (n) => byteSwap(n);
|
||||
/** @deprecated */
|
||||
exports.byteSwapIfBE = exports.swap8IfBE;
|
||||
/** In place byte swap for Uint32Array */
|
||||
function byteSwap32(arr) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i] = byteSwap(arr[i]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
exports.swap32IfBE = exports.isLE
|
||||
? (u) => u
|
||||
: byteSwap32;
|
||||
// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex
|
||||
const hasHexBuiltin = /* @__PURE__ */ (() =>
|
||||
// @ts-ignore
|
||||
typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();
|
||||
// Array where index 0xf0 (240) is mapped to string 'f0'
|
||||
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
|
||||
/**
|
||||
* Convert byte array to hex string. Uses built-in function, when available.
|
||||
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
|
||||
*/
|
||||
function bytesToHex(bytes) {
|
||||
abytes(bytes);
|
||||
// @ts-ignore
|
||||
if (hasHexBuiltin)
|
||||
return bytes.toHex();
|
||||
// pre-caching improves the speed 6x
|
||||
let hex = '';
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
hex += hexes[bytes[i]];
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
// We use optimized technique to convert hex string to byte array
|
||||
const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
||||
function asciiToBase16(ch) {
|
||||
if (ch >= asciis._0 && ch <= asciis._9)
|
||||
return ch - asciis._0; // '2' => 50-48
|
||||
if (ch >= asciis.A && ch <= asciis.F)
|
||||
return ch - (asciis.A - 10); // 'B' => 66-(65-10)
|
||||
if (ch >= asciis.a && ch <= asciis.f)
|
||||
return ch - (asciis.a - 10); // 'b' => 98-(97-10)
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Convert hex string to byte array. Uses built-in function, when available.
|
||||
* @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
|
||||
*/
|
||||
function hexToBytes(hex) {
|
||||
if (typeof hex !== 'string')
|
||||
throw new Error('hex string expected, got ' + typeof hex);
|
||||
// @ts-ignore
|
||||
if (hasHexBuiltin)
|
||||
return Uint8Array.fromHex(hex);
|
||||
const hl = hex.length;
|
||||
const al = hl / 2;
|
||||
if (hl % 2)
|
||||
throw new Error('hex string expected, got unpadded hex of length ' + hl);
|
||||
const array = new Uint8Array(al);
|
||||
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
||||
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
||||
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
||||
if (n1 === undefined || n2 === undefined) {
|
||||
const char = hex[hi] + hex[hi + 1];
|
||||
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
||||
}
|
||||
array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
|
||||
}
|
||||
return array;
|
||||
}
|
||||
/**
|
||||
* There is no setImmediate in browser and setTimeout is slow.
|
||||
* Call of async fn will return Promise, which will be fullfiled only on
|
||||
* next scheduler queue processing step and this is exactly what we need.
|
||||
*/
|
||||
const nextTick = async () => { };
|
||||
exports.nextTick = nextTick;
|
||||
/** Returns control to thread each 'tick' ms to avoid blocking. */
|
||||
async function asyncLoop(iters, tick, cb) {
|
||||
let ts = Date.now();
|
||||
for (let i = 0; i < iters; i++) {
|
||||
cb(i);
|
||||
// Date.now() is not monotonic, so in case if clock goes backwards we return return control too
|
||||
const diff = Date.now() - ts;
|
||||
if (diff >= 0 && diff < tick)
|
||||
continue;
|
||||
await (0, exports.nextTick)();
|
||||
ts += diff;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Converts string to bytes using UTF8 encoding.
|
||||
* @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])
|
||||
*/
|
||||
function utf8ToBytes(str) {
|
||||
if (typeof str !== 'string')
|
||||
throw new Error('string expected');
|
||||
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
|
||||
}
|
||||
/**
|
||||
* Converts bytes to string using UTF8 encoding.
|
||||
* @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
|
||||
*/
|
||||
function bytesToUtf8(bytes) {
|
||||
return new TextDecoder().decode(bytes);
|
||||
}
|
||||
/**
|
||||
* Normalizes (non-hex) string or Uint8Array to Uint8Array.
|
||||
* Warning: when Uint8Array is passed, it would NOT get copied.
|
||||
* Keep in mind for future mutable operations.
|
||||
*/
|
||||
function toBytes(data) {
|
||||
if (typeof data === 'string')
|
||||
data = utf8ToBytes(data);
|
||||
abytes(data);
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* Helper for KDFs: consumes uint8array or string.
|
||||
* When string is passed, does utf8 decoding, using TextDecoder.
|
||||
*/
|
||||
function kdfInputToBytes(data) {
|
||||
if (typeof data === 'string')
|
||||
data = utf8ToBytes(data);
|
||||
abytes(data);
|
||||
return data;
|
||||
}
|
||||
/** Copies several Uint8Arrays into one. */
|
||||
function concatBytes(...arrays) {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < arrays.length; i++) {
|
||||
const a = arrays[i];
|
||||
abytes(a);
|
||||
sum += a.length;
|
||||
}
|
||||
const res = new Uint8Array(sum);
|
||||
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
||||
const a = arrays[i];
|
||||
res.set(a, pad);
|
||||
pad += a.length;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function checkOpts(defaults, opts) {
|
||||
if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')
|
||||
throw new Error('options should be object or undefined');
|
||||
const merged = Object.assign(defaults, opts);
|
||||
return merged;
|
||||
}
|
||||
/** For runtime check if class implements interface */
|
||||
class Hash {
|
||||
}
|
||||
exports.Hash = Hash;
|
||||
/** Wraps hash function, creating an interface on top of it */
|
||||
function createHasher(hashCons) {
|
||||
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
|
||||
const tmp = hashCons();
|
||||
hashC.outputLen = tmp.outputLen;
|
||||
hashC.blockLen = tmp.blockLen;
|
||||
hashC.create = () => hashCons();
|
||||
return hashC;
|
||||
}
|
||||
function createOptHasher(hashCons) {
|
||||
const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();
|
||||
const tmp = hashCons({});
|
||||
hashC.outputLen = tmp.outputLen;
|
||||
hashC.blockLen = tmp.blockLen;
|
||||
hashC.create = (opts) => hashCons(opts);
|
||||
return hashC;
|
||||
}
|
||||
function createXOFer(hashCons) {
|
||||
const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();
|
||||
const tmp = hashCons({});
|
||||
hashC.outputLen = tmp.outputLen;
|
||||
hashC.blockLen = tmp.blockLen;
|
||||
hashC.create = (opts) => hashCons(opts);
|
||||
return hashC;
|
||||
}
|
||||
exports.wrapConstructor = createHasher;
|
||||
exports.wrapConstructorWithOpts = createOptHasher;
|
||||
exports.wrapXOFConstructorWithOpts = createXOFer;
|
||||
/** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */
|
||||
function randomBytes(bytesLength = 32) {
|
||||
if (crypto_1.crypto && typeof crypto_1.crypto.getRandomValues === 'function') {
|
||||
return crypto_1.crypto.getRandomValues(new Uint8Array(bytesLength));
|
||||
}
|
||||
// Legacy Node.js compatibility
|
||||
if (crypto_1.crypto && typeof crypto_1.crypto.randomBytes === 'function') {
|
||||
return Uint8Array.from(crypto_1.crypto.randomBytes(bytesLength));
|
||||
}
|
||||
throw new Error('crypto.getRandomValues must be defined');
|
||||
}
|
||||
//# sourceMappingURL=utils.js.map
|
||||
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createParserServices = createParserServices;
|
||||
function createParserServices(astMaps, program) {
|
||||
if (!program) {
|
||||
return {
|
||||
emitDecoratorMetadata: undefined,
|
||||
experimentalDecorators: undefined,
|
||||
isolatedDeclarations: undefined,
|
||||
program,
|
||||
// we always return the node maps because
|
||||
// (a) they don't require type info and
|
||||
// (b) they can be useful when using some of TS's internal non-type-aware AST utils
|
||||
...astMaps,
|
||||
};
|
||||
}
|
||||
const checker = program.getTypeChecker();
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
return {
|
||||
program,
|
||||
// not set in the config is the same as off
|
||||
emitDecoratorMetadata: compilerOptions.emitDecoratorMetadata ?? false,
|
||||
experimentalDecorators: compilerOptions.experimentalDecorators ?? false,
|
||||
isolatedDeclarations: compilerOptions.isolatedDeclarations ?? false,
|
||||
...astMaps,
|
||||
getContextualType: node => checker.getContextualType(astMaps.esTreeNodeToTSNodeMap.get(node)),
|
||||
getResolvedSignature: node => checker.getResolvedSignature(astMaps.esTreeNodeToTSNodeMap.get(node)),
|
||||
getSymbolAtLocation: node => checker.getSymbolAtLocation(astMaps.esTreeNodeToTSNodeMap.get(node)),
|
||||
getTypeAtLocation: node => checker.getTypeAtLocation(astMaps.esTreeNodeToTSNodeMap.get(node)),
|
||||
getTypeFromTypeNode: node => checker.getTypeFromTypeNode(astMaps.esTreeNodeToTSNodeMap.get(node)),
|
||||
getTypeOfSymbolAtLocation: (symbol, node) => checker.getTypeOfSymbolAtLocation(symbol, astMaps.esTreeNodeToTSNodeMap.get(node)),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,698 @@
|
||||
'use strict'
|
||||
const test = require('tape')
|
||||
const fresh = require('import-fresh')
|
||||
const pinoStdSerializers = require('pino-std-serializers')
|
||||
const pino = require('../browser')
|
||||
|
||||
levelTest('fatal')
|
||||
levelTest('error')
|
||||
levelTest('warn')
|
||||
levelTest('info')
|
||||
levelTest('debug')
|
||||
levelTest('trace')
|
||||
|
||||
test('silent level', ({ end, fail, pass }) => {
|
||||
const instance = pino({
|
||||
level: 'silent',
|
||||
browser: { write: fail }
|
||||
})
|
||||
instance.info('test')
|
||||
const child = instance.child({ test: 'test' })
|
||||
child.info('msg-test')
|
||||
// use setTimeout because setImmediate isn't supported in most browsers
|
||||
setTimeout(() => {
|
||||
pass()
|
||||
end()
|
||||
}, 0)
|
||||
})
|
||||
|
||||
test('enabled false', ({ end, fail, pass }) => {
|
||||
const instance = pino({
|
||||
enabled: false,
|
||||
browser: { write: fail }
|
||||
})
|
||||
instance.info('test')
|
||||
const child = instance.child({ test: 'test' })
|
||||
child.info('msg-test')
|
||||
// use setTimeout because setImmediate isn't supported in most browsers
|
||||
setTimeout(() => {
|
||||
pass()
|
||||
end()
|
||||
}, 0)
|
||||
})
|
||||
|
||||
test('throw if creating child without bindings', ({ end, throws }) => {
|
||||
const instance = pino()
|
||||
throws(() => instance.child())
|
||||
end()
|
||||
})
|
||||
|
||||
test('stubs write, flush and ee methods on instance', ({ end, ok, is }) => {
|
||||
const instance = pino()
|
||||
|
||||
ok(isFunc(instance.setMaxListeners))
|
||||
ok(isFunc(instance.getMaxListeners))
|
||||
ok(isFunc(instance.emit))
|
||||
ok(isFunc(instance.addListener))
|
||||
ok(isFunc(instance.on))
|
||||
ok(isFunc(instance.prependListener))
|
||||
ok(isFunc(instance.once))
|
||||
ok(isFunc(instance.prependOnceListener))
|
||||
ok(isFunc(instance.removeListener))
|
||||
ok(isFunc(instance.removeAllListeners))
|
||||
ok(isFunc(instance.listeners))
|
||||
ok(isFunc(instance.listenerCount))
|
||||
ok(isFunc(instance.eventNames))
|
||||
ok(isFunc(instance.write))
|
||||
ok(isFunc(instance.flush))
|
||||
|
||||
is(instance.on(), undefined)
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('exposes levels object', ({ end, same }) => {
|
||||
same(pino.levels, {
|
||||
values: {
|
||||
fatal: 60,
|
||||
error: 50,
|
||||
warn: 40,
|
||||
info: 30,
|
||||
debug: 20,
|
||||
trace: 10
|
||||
},
|
||||
labels: {
|
||||
10: 'trace',
|
||||
20: 'debug',
|
||||
30: 'info',
|
||||
40: 'warn',
|
||||
50: 'error',
|
||||
60: 'fatal'
|
||||
}
|
||||
})
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('exposes faux stdSerializers', ({ end, ok, same }) => {
|
||||
ok(pino.stdSerializers)
|
||||
// make sure faux stdSerializers match pino-std-serializers
|
||||
for (const serializer in pinoStdSerializers) {
|
||||
ok(pino.stdSerializers[serializer], `pino.stdSerializers.${serializer}`)
|
||||
}
|
||||
// confirm faux methods return empty objects
|
||||
same(pino.stdSerializers.req(), {})
|
||||
same(pino.stdSerializers.mapHttpRequest(), {})
|
||||
same(pino.stdSerializers.mapHttpResponse(), {})
|
||||
same(pino.stdSerializers.res(), {})
|
||||
// confirm wrapping function is a passthrough
|
||||
const noChange = { foo: 'bar', fuz: 42 }
|
||||
same(pino.stdSerializers.wrapRequestSerializer(noChange), noChange)
|
||||
same(pino.stdSerializers.wrapResponseSerializer(noChange), noChange)
|
||||
end()
|
||||
})
|
||||
|
||||
test('exposes err stdSerializer', ({ end, ok }) => {
|
||||
ok(pino.stdSerializers.err)
|
||||
ok(pino.stdSerializers.err(Error()))
|
||||
end()
|
||||
})
|
||||
|
||||
consoleMethodTest('error')
|
||||
consoleMethodTest('fatal', 'error')
|
||||
consoleMethodTest('warn')
|
||||
consoleMethodTest('info')
|
||||
consoleMethodTest('debug')
|
||||
consoleMethodTest('trace')
|
||||
absentConsoleMethodTest('error', 'log')
|
||||
absentConsoleMethodTest('warn', 'error')
|
||||
absentConsoleMethodTest('info', 'log')
|
||||
absentConsoleMethodTest('debug', 'log')
|
||||
absentConsoleMethodTest('trace', 'log')
|
||||
|
||||
// do not run this with airtap
|
||||
if (process.title !== 'browser') {
|
||||
test('in absence of console, log methods become noops', ({ end, ok }) => {
|
||||
const console = global.console
|
||||
delete global.console
|
||||
const instance = fresh('../browser')()
|
||||
global.console = console
|
||||
ok(fnName(instance.log).match(/noop/))
|
||||
ok(fnName(instance.fatal).match(/noop/))
|
||||
ok(fnName(instance.error).match(/noop/))
|
||||
ok(fnName(instance.warn).match(/noop/))
|
||||
ok(fnName(instance.info).match(/noop/))
|
||||
ok(fnName(instance.debug).match(/noop/))
|
||||
ok(fnName(instance.trace).match(/noop/))
|
||||
end()
|
||||
})
|
||||
}
|
||||
|
||||
test('opts.browser.asObject logs pino-like object to console', ({ end, ok, is }) => {
|
||||
const info = console.info
|
||||
console.info = function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test')
|
||||
ok(o.time)
|
||||
console.info = info
|
||||
}
|
||||
const instance = require('../browser')({
|
||||
browser: {
|
||||
asObject: true
|
||||
}
|
||||
})
|
||||
|
||||
instance.info('test')
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.asObject uses opts.messageKey in logs', ({ end, ok, is }) => {
|
||||
const messageKey = 'message'
|
||||
const instance = require('../browser')({
|
||||
messageKey,
|
||||
browser: {
|
||||
asObject: true,
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o[messageKey], 'test')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.info('test')
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.asObjectBindingsOnly passes the bindings but keep the message unformatted', ({ end, ok, is, deepEqual }) => {
|
||||
const messageKey = 'message'
|
||||
const instance = require('../browser')({
|
||||
messageKey,
|
||||
browser: {
|
||||
asObjectBindingsOnly: true,
|
||||
write: function (o, msg, ...args) {
|
||||
is(o.level, 30)
|
||||
ok(o.time)
|
||||
is(msg, 'test %s')
|
||||
deepEqual(args, ['foo'])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.info('test %s', 'foo')
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.formatters (level) logs pino-like object to console', ({ end, ok, is }) => {
|
||||
const info = console.info
|
||||
console.info = function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.label, 'info')
|
||||
is(o.msg, 'test')
|
||||
ok(o.time)
|
||||
console.info = info
|
||||
}
|
||||
const instance = require('../browser')({
|
||||
browser: {
|
||||
formatters: {
|
||||
level (label, number) {
|
||||
return { label, level: number }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.info('test')
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.formatters (log) logs pino-like object to console', ({ end, ok, is }) => {
|
||||
const info = console.info
|
||||
console.info = function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test')
|
||||
is(o.hello, 'world')
|
||||
is(o.newField, 'test')
|
||||
ok(o.time, `Logged at ${o.time}`)
|
||||
console.info = info
|
||||
}
|
||||
const instance = require('../browser')({
|
||||
browser: {
|
||||
formatters: {
|
||||
log (o) {
|
||||
return { ...o, newField: 'test', time: `Logged at ${o.time}` }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.info({ hello: 'world' }, 'test')
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.reportCaller adds caller in asObject mode', ({ end, ok }) => {
|
||||
const instance = require('../browser')({
|
||||
browser: {
|
||||
asObject: true,
|
||||
reportCaller: true,
|
||||
write: function (o) {
|
||||
ok(typeof o.caller === 'string' && o.caller.length > 0, 'has caller string')
|
||||
ok(/:\\d+:\\d+/.test(o.caller) || /:\d+:\d+/.test(o.caller), `caller has line:col pattern: ${o.caller}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.info('test')
|
||||
end()
|
||||
})
|
||||
|
||||
// NOTE: Default (non-object) mode caller string is covered in docs
|
||||
// and manually verified. Keeping the test minimal to avoid cross-env flakiness.
|
||||
|
||||
test('opts.browser.serialize and opts.browser.transmit only serializes log data once', ({ end, ok, is }) => {
|
||||
const instance = require('../browser')({
|
||||
serializers: {
|
||||
extras (data) {
|
||||
return { serializedExtras: data }
|
||||
}
|
||||
},
|
||||
browser: {
|
||||
serialize: ['extras'],
|
||||
transmit: {
|
||||
level: 'info',
|
||||
send (level, o) {
|
||||
is(o.messages[0].extras.serializedExtras, 'world')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.info({ extras: 'world' }, 'test')
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.serialize and opts.asObject only serializes log data once', ({ end, ok, is }) => {
|
||||
const instance = require('../browser')({
|
||||
serializers: {
|
||||
extras (data) {
|
||||
return { serializedExtras: data }
|
||||
}
|
||||
},
|
||||
browser: {
|
||||
serialize: ['extras'],
|
||||
asObject: true,
|
||||
write: function (o) {
|
||||
is(o.extras.serializedExtras, 'world')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.info({ extras: 'world' }, 'test')
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.serialize, opts.asObject and opts.browser.transmit only serializes log data once', ({ end, ok, is }) => {
|
||||
const instance = require('../browser')({
|
||||
serializers: {
|
||||
extras (data) {
|
||||
return { serializedExtras: data }
|
||||
}
|
||||
},
|
||||
browser: {
|
||||
serialize: ['extras'],
|
||||
asObject: true,
|
||||
transmit: {
|
||||
send (level, o) {
|
||||
is(o.messages[0].extras.serializedExtras, 'world')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.info({ extras: 'world' }, 'test')
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write func log single string', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.info('test')
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write func string joining', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test test2 test3')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.info('test %s %s', 'test2', 'test3')
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write func string joining when asObject is true', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
asObject: true,
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test test2 test3')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.info('test %s %s', 'test2', 'test3')
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write func string object joining', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test {"test":"test2"} {"test":"test3"}')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.info('test %j %j', { test: 'test2' }, { test: 'test3' })
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write func string object joining when asObject is true', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
asObject: true,
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test {"test":"test2"} {"test":"test3"}')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.info('test %j %j', { test: 'test2' }, { test: 'test3' })
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write func string interpolation', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test2 test ({"test":"test3"})')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.info('%s test (%j)', 'test2', { test: 'test3' })
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write func number', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 1)
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.info(1)
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write func log single object', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write: function (o) {
|
||||
is(o.level, 30)
|
||||
is(o.test, 'test')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.info({ test: 'test' })
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write obj writes to methods corresponding to level', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write: {
|
||||
error: function (o) {
|
||||
is(o.level, 50)
|
||||
is(o.test, 'test')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.error({ test: 'test' })
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.asObject/write supports child loggers', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write (o) {
|
||||
is(o.level, 30)
|
||||
is(o.test, 'test')
|
||||
is(o.msg, 'msg-test')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
const child = instance.child({ test: 'test' })
|
||||
child.info('msg-test')
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.asObject/write supports child child loggers', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write (o) {
|
||||
is(o.level, 30)
|
||||
is(o.test, 'test')
|
||||
is(o.foo, 'bar')
|
||||
is(o.msg, 'msg-test')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
const child = instance.child({ test: 'test' }).child({ foo: 'bar' })
|
||||
child.info('msg-test')
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.asObject/write supports child child child loggers', ({ end, ok, is }) => {
|
||||
const instance = pino({
|
||||
browser: {
|
||||
write (o) {
|
||||
is(o.level, 30)
|
||||
is(o.test, 'test')
|
||||
is(o.foo, 'bar')
|
||||
is(o.baz, 'bop')
|
||||
is(o.msg, 'msg-test')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
})
|
||||
const child = instance.child({ test: 'test' }).child({ foo: 'bar' }).child({ baz: 'bop' })
|
||||
child.info('msg-test')
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.asObject defensively mitigates naughty numbers', ({ end, pass }) => {
|
||||
const instance = pino({
|
||||
browser: { asObject: true, write: () => {} }
|
||||
})
|
||||
const child = instance.child({ test: 'test' })
|
||||
child._childLevel = -10
|
||||
child.info('test')
|
||||
pass() // if we reached here, there was no infinite loop, so, .. pass.
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
test('opts.browser.write obj falls back to console where a method is not supplied', ({ end, ok, is }) => {
|
||||
const info = console.info
|
||||
console.info = (o) => {
|
||||
is(o.level, 30)
|
||||
is(o.msg, 'test')
|
||||
ok(o.time)
|
||||
console.info = info
|
||||
}
|
||||
const instance = require('../browser')({
|
||||
browser: {
|
||||
write: {
|
||||
error (o) {
|
||||
is(o.level, 50)
|
||||
is(o.test, 'test')
|
||||
ok(o.time)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.error({ test: 'test' })
|
||||
instance.info('test')
|
||||
|
||||
end()
|
||||
})
|
||||
|
||||
function levelTest (name) {
|
||||
test(name + ' logs', ({ end, is }) => {
|
||||
const msg = 'hello world'
|
||||
sink(name, (args) => {
|
||||
is(args[0], msg)
|
||||
end()
|
||||
})
|
||||
pino({ level: name })[name](msg)
|
||||
})
|
||||
|
||||
test('passing objects at level ' + name, ({ end, is }) => {
|
||||
const msg = { hello: 'world' }
|
||||
sink(name, (args) => {
|
||||
is(args[0], msg)
|
||||
end()
|
||||
})
|
||||
pino({ level: name })[name](msg)
|
||||
})
|
||||
|
||||
test('passing an object and a string at level ' + name, ({ end, is }) => {
|
||||
const a = { hello: 'world' }
|
||||
const b = 'a string'
|
||||
sink(name, (args) => {
|
||||
is(args[0], a)
|
||||
is(args[1], b)
|
||||
end()
|
||||
})
|
||||
pino({ level: name })[name](a, b)
|
||||
})
|
||||
|
||||
test('formatting logs as ' + name, ({ end, is }) => {
|
||||
sink(name, (args) => {
|
||||
is(args[0], 'hello %d')
|
||||
is(args[1], 42)
|
||||
end()
|
||||
})
|
||||
pino({ level: name })[name]('hello %d', 42)
|
||||
})
|
||||
|
||||
test('passing error at level ' + name, ({ end, is }) => {
|
||||
const err = new Error('myerror')
|
||||
sink(name, (args) => {
|
||||
is(args[0], err)
|
||||
end()
|
||||
})
|
||||
pino({ level: name })[name](err)
|
||||
})
|
||||
|
||||
test('passing error with a serializer at level ' + name, ({ end, is }) => {
|
||||
// in browser - should have no effect (should not crash)
|
||||
const err = new Error('myerror')
|
||||
sink(name, (args) => {
|
||||
is(args[0].err, err)
|
||||
end()
|
||||
})
|
||||
const instance = pino({
|
||||
level: name,
|
||||
serializers: {
|
||||
err: pino.stdSerializers.err
|
||||
}
|
||||
})
|
||||
instance[name]({ err })
|
||||
})
|
||||
|
||||
test('child logger for level ' + name, ({ end, is }) => {
|
||||
const msg = 'hello world'
|
||||
const parent = { hello: 'world' }
|
||||
sink(name, (args) => {
|
||||
is(args[0], parent)
|
||||
is(args[1], msg)
|
||||
end()
|
||||
})
|
||||
const instance = pino({ level: name })
|
||||
const child = instance.child(parent)
|
||||
child[name](msg)
|
||||
})
|
||||
|
||||
test('child-child logger for level ' + name, ({ end, is }) => {
|
||||
const msg = 'hello world'
|
||||
const grandParent = { hello: 'world' }
|
||||
const parent = { hello: 'you' }
|
||||
sink(name, (args) => {
|
||||
is(args[0], grandParent)
|
||||
is(args[1], parent)
|
||||
is(args[2], msg)
|
||||
end()
|
||||
})
|
||||
const instance = pino({ level: name })
|
||||
const child = instance.child(grandParent).child(parent)
|
||||
child[name](msg)
|
||||
})
|
||||
}
|
||||
|
||||
function consoleMethodTest (level, method) {
|
||||
if (!method) method = level
|
||||
test('pino().' + level + ' uses console.' + method, ({ end, is }) => {
|
||||
sink(method, (args) => {
|
||||
is(args[0], 'test')
|
||||
end()
|
||||
})
|
||||
const instance = require('../browser')({ level })
|
||||
instance[level]('test')
|
||||
})
|
||||
}
|
||||
|
||||
function absentConsoleMethodTest (method, fallback) {
|
||||
test('in absence of console.' + method + ', console.' + fallback + ' is used', ({ end, is }) => {
|
||||
const fn = console[method]
|
||||
console[method] = undefined
|
||||
sink(fallback, function (args) {
|
||||
is(args[0], 'test')
|
||||
end()
|
||||
console[method] = fn
|
||||
})
|
||||
const instance = require('../browser')({ level: method })
|
||||
instance[method]('test')
|
||||
})
|
||||
}
|
||||
|
||||
function isFunc (fn) { return typeof fn === 'function' }
|
||||
function fnName (fn) {
|
||||
const rx = /^\s*function\s*([^(]*)/i
|
||||
const match = rx.exec(fn)
|
||||
return match && match[1]
|
||||
}
|
||||
function sink (method, fn) {
|
||||
if (method === 'fatal') method = 'error'
|
||||
const orig = console[method]
|
||||
console[method] = function () {
|
||||
console[method] = orig
|
||||
fn(Array.prototype.slice.call(arguments))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @fileoverview Handle logging for ESLint
|
||||
* @author Gyandeep Singh
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
/* eslint no-console: "off" -- Logging util */
|
||||
|
||||
/* c8 ignore next */
|
||||
module.exports = {
|
||||
/**
|
||||
* Cover for console.info
|
||||
* @param {...any} args The elements to log.
|
||||
* @returns {void}
|
||||
*/
|
||||
info(...args) {
|
||||
console.log(...args);
|
||||
},
|
||||
|
||||
/**
|
||||
* Cover for console.warn
|
||||
* @param {...any} args The elements to log.
|
||||
* @returns {void}
|
||||
*/
|
||||
warn(...args) {
|
||||
console.warn(...args);
|
||||
},
|
||||
|
||||
/**
|
||||
* Cover for console.error
|
||||
* @param {...any} args The elements to log.
|
||||
* @returns {void}
|
||||
*/
|
||||
error(...args) {
|
||||
console.error(...args);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
var id = 0;
|
||||
function _classPrivateFieldKey(e) {
|
||||
return "__private_" + id++ + "_" + e;
|
||||
}
|
||||
export { _classPrivateFieldKey as default };
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
/**
|
||||
* This is a compatibility ruleset that:
|
||||
* - disables rules from eslint:recommended which are already handled by TypeScript.
|
||||
* - enables rules that make sense due to TS's typechecking / transpilation.
|
||||
*/
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
const eslint_recommended_raw_1 = __importDefault(require("../eslint-recommended-raw"));
|
||||
module.exports = {
|
||||
overrides: [(0, eslint_recommended_raw_1.default)('glob')],
|
||||
};
|
||||
@@ -0,0 +1,124 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "àmi", verb: "ní" },
|
||||
file: { unit: "bytes", verb: "ní" },
|
||||
array: { unit: "nkan", verb: "ní" },
|
||||
set: { unit: "nkan", verb: "ní" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const FormatDictionary: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "ẹ̀rọ ìbáwọlé",
|
||||
email: "àdírẹ́sì ìmẹ́lì",
|
||||
url: "URL",
|
||||
emoji: "emoji",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "àkókò ISO",
|
||||
date: "ọjọ́ ISO",
|
||||
time: "àkókò ISO",
|
||||
duration: "àkókò tó pé ISO",
|
||||
ipv4: "àdírẹ́sì IPv4",
|
||||
ipv6: "àdírẹ́sì IPv6",
|
||||
cidrv4: "àgbègbè IPv4",
|
||||
cidrv6: "àgbègbè IPv6",
|
||||
base64: "ọ̀rọ̀ tí a kọ́ ní base64",
|
||||
base64url: "ọ̀rọ̀ base64url",
|
||||
json_string: "ọ̀rọ̀ JSON",
|
||||
e164: "nọ́mbà E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "ẹ̀rọ ìbáwọlé",
|
||||
};
|
||||
|
||||
const TypeDictionary: {
|
||||
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
|
||||
} = {
|
||||
nan: "NaN",
|
||||
number: "nọ́mbà",
|
||||
array: "akopọ",
|
||||
};
|
||||
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `Ìbáwọlé aṣìṣe: a ní láti fi instanceof ${issue.expected}, àmọ̀ a rí ${received}`;
|
||||
}
|
||||
return `Ìbáwọlé aṣìṣe: a ní láti fi ${expected}, àmọ̀ a rí ${received}`;
|
||||
}
|
||||
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1) return `Ìbáwọlé aṣìṣe: a ní láti fi ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Àṣàyàn aṣìṣe: yan ọ̀kan lára ${util.joinValues(issue.values, "|")}`;
|
||||
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Tó pọ̀ jù: a ní láti jẹ́ pé ${issue.origin ?? "iye"} ${sizing.verb} ${adj}${issue.maximum} ${sizing.unit}`;
|
||||
return `Tó pọ̀ jù: a ní láti jẹ́ ${adj}${issue.maximum}`;
|
||||
}
|
||||
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Kéré ju: a ní láti jẹ́ pé ${issue.origin} ${sizing.verb} ${adj}${issue.minimum} ${sizing.unit}`;
|
||||
return `Kéré ju: a ní láti jẹ́ ${adj}${issue.minimum}`;
|
||||
}
|
||||
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `Ọ̀rọ̀ aṣìṣe: gbọ́dọ̀ bẹ̀rẹ̀ pẹ̀lú "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with") return `Ọ̀rọ̀ aṣìṣe: gbọ́dọ̀ parí pẹ̀lú "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `Ọ̀rọ̀ aṣìṣe: gbọ́dọ̀ ní "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `Ọ̀rọ̀ aṣìṣe: gbọ́dọ̀ bá àpẹẹrẹ mu ${_issue.pattern}`;
|
||||
return `Aṣìṣe: ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
|
||||
case "not_multiple_of":
|
||||
return `Nọ́mbà aṣìṣe: gbọ́dọ̀ jẹ́ èyà pípín ti ${issue.divisor}`;
|
||||
|
||||
case "unrecognized_keys":
|
||||
return `Bọtìnì àìmọ̀: ${util.joinValues(issue.keys, ", ")}`;
|
||||
|
||||
case "invalid_key":
|
||||
return `Bọtìnì aṣìṣe nínú ${issue.origin}`;
|
||||
|
||||
case "invalid_union":
|
||||
return "Ìbáwọlé aṣìṣe";
|
||||
|
||||
case "invalid_element":
|
||||
return `Iye aṣìṣe nínú ${issue.origin}`;
|
||||
|
||||
default:
|
||||
return "Ìbáwọlé aṣìṣe";
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
type Values = 'always' | 'in-intersections' | 'in-unions' | 'in-unions-and-intersections' | 'never';
|
||||
export type Options = [
|
||||
{
|
||||
allowAliases?: Values;
|
||||
allowCallbacks?: 'always' | 'never';
|
||||
allowConditionalTypes?: 'always' | 'never';
|
||||
allowConstructors?: 'always' | 'never';
|
||||
allowGenerics?: 'always' | 'never';
|
||||
allowLiterals?: Values;
|
||||
allowMappedTypes?: Values;
|
||||
allowTupleTypes?: Values;
|
||||
}
|
||||
];
|
||||
export type MessageIds = 'noCompositionAlias' | 'noTypeAlias';
|
||||
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,216 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.$ZodRealError = exports.$ZodError = void 0;
|
||||
exports.flattenError = flattenError;
|
||||
exports.formatError = formatError;
|
||||
exports.treeifyError = treeifyError;
|
||||
exports.toDotPath = toDotPath;
|
||||
exports.prettifyError = prettifyError;
|
||||
const core_js_1 = require("./core.cjs");
|
||||
const util = __importStar(require("./util.cjs"));
|
||||
const initializer = (inst, def) => {
|
||||
inst.name = "$ZodError";
|
||||
Object.defineProperty(inst, "_zod", {
|
||||
value: inst._zod,
|
||||
enumerable: false,
|
||||
});
|
||||
Object.defineProperty(inst, "issues", {
|
||||
value: def,
|
||||
enumerable: false,
|
||||
});
|
||||
inst.message = JSON.stringify(def, util.jsonStringifyReplacer, 2);
|
||||
Object.defineProperty(inst, "toString", {
|
||||
value: () => inst.message,
|
||||
enumerable: false,
|
||||
});
|
||||
};
|
||||
exports.$ZodError = (0, core_js_1.$constructor)("$ZodError", initializer);
|
||||
exports.$ZodRealError = (0, core_js_1.$constructor)("$ZodError", initializer, { Parent: Error });
|
||||
function flattenError(error, mapper = (issue) => issue.message) {
|
||||
const fieldErrors = {};
|
||||
const formErrors = [];
|
||||
for (const sub of error.issues) {
|
||||
if (sub.path.length > 0) {
|
||||
fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
|
||||
fieldErrors[sub.path[0]].push(mapper(sub));
|
||||
}
|
||||
else {
|
||||
formErrors.push(mapper(sub));
|
||||
}
|
||||
}
|
||||
return { formErrors, fieldErrors };
|
||||
}
|
||||
function formatError(error, mapper = (issue) => issue.message) {
|
||||
const fieldErrors = { _errors: [] };
|
||||
const processError = (error, path = []) => {
|
||||
for (const issue of error.issues) {
|
||||
if (issue.code === "invalid_union" && issue.errors.length) {
|
||||
issue.errors.map((issues) => processError({ issues }, [...path, ...issue.path]));
|
||||
}
|
||||
else if (issue.code === "invalid_key") {
|
||||
processError({ issues: issue.issues }, [...path, ...issue.path]);
|
||||
}
|
||||
else if (issue.code === "invalid_element") {
|
||||
processError({ issues: issue.issues }, [...path, ...issue.path]);
|
||||
}
|
||||
else {
|
||||
const fullpath = [...path, ...issue.path];
|
||||
if (fullpath.length === 0) {
|
||||
fieldErrors._errors.push(mapper(issue));
|
||||
}
|
||||
else {
|
||||
let curr = fieldErrors;
|
||||
let i = 0;
|
||||
while (i < fullpath.length) {
|
||||
const el = fullpath[i];
|
||||
const terminal = i === fullpath.length - 1;
|
||||
if (!terminal) {
|
||||
curr[el] = curr[el] || { _errors: [] };
|
||||
}
|
||||
else {
|
||||
curr[el] = curr[el] || { _errors: [] };
|
||||
curr[el]._errors.push(mapper(issue));
|
||||
}
|
||||
curr = curr[el];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
processError(error);
|
||||
return fieldErrors;
|
||||
}
|
||||
function treeifyError(error, mapper = (issue) => issue.message) {
|
||||
const result = { errors: [] };
|
||||
const processError = (error, path = []) => {
|
||||
var _a, _b;
|
||||
for (const issue of error.issues) {
|
||||
if (issue.code === "invalid_union" && issue.errors.length) {
|
||||
// regular union error
|
||||
issue.errors.map((issues) => processError({ issues }, [...path, ...issue.path]));
|
||||
}
|
||||
else if (issue.code === "invalid_key") {
|
||||
processError({ issues: issue.issues }, [...path, ...issue.path]);
|
||||
}
|
||||
else if (issue.code === "invalid_element") {
|
||||
processError({ issues: issue.issues }, [...path, ...issue.path]);
|
||||
}
|
||||
else {
|
||||
const fullpath = [...path, ...issue.path];
|
||||
if (fullpath.length === 0) {
|
||||
result.errors.push(mapper(issue));
|
||||
continue;
|
||||
}
|
||||
let curr = result;
|
||||
let i = 0;
|
||||
while (i < fullpath.length) {
|
||||
const el = fullpath[i];
|
||||
const terminal = i === fullpath.length - 1;
|
||||
if (typeof el === "string") {
|
||||
curr.properties ?? (curr.properties = {});
|
||||
(_a = curr.properties)[el] ?? (_a[el] = { errors: [] });
|
||||
curr = curr.properties[el];
|
||||
}
|
||||
else {
|
||||
curr.items ?? (curr.items = []);
|
||||
(_b = curr.items)[el] ?? (_b[el] = { errors: [] });
|
||||
curr = curr.items[el];
|
||||
}
|
||||
if (terminal) {
|
||||
curr.errors.push(mapper(issue));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
processError(error);
|
||||
return result;
|
||||
}
|
||||
/** Format a ZodError as a human-readable string in the following form.
|
||||
*
|
||||
* From
|
||||
*
|
||||
* ```ts
|
||||
* ZodError {
|
||||
* issues: [
|
||||
* {
|
||||
* expected: 'string',
|
||||
* code: 'invalid_type',
|
||||
* path: [ 'username' ],
|
||||
* message: 'Invalid input: expected string'
|
||||
* },
|
||||
* {
|
||||
* expected: 'number',
|
||||
* code: 'invalid_type',
|
||||
* path: [ 'favoriteNumbers', 1 ],
|
||||
* message: 'Invalid input: expected number'
|
||||
* }
|
||||
* ];
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* to
|
||||
*
|
||||
* ```
|
||||
* username
|
||||
* ✖ Expected number, received string at "username
|
||||
* favoriteNumbers[0]
|
||||
* ✖ Invalid input: expected number
|
||||
* ```
|
||||
*/
|
||||
function toDotPath(_path) {
|
||||
const segs = [];
|
||||
const path = _path.map((seg) => (typeof seg === "object" ? seg.key : seg));
|
||||
for (const seg of path) {
|
||||
if (typeof seg === "number")
|
||||
segs.push(`[${seg}]`);
|
||||
else if (typeof seg === "symbol")
|
||||
segs.push(`[${JSON.stringify(String(seg))}]`);
|
||||
else if (/[^\w$]/.test(seg))
|
||||
segs.push(`[${JSON.stringify(seg)}]`);
|
||||
else {
|
||||
if (segs.length)
|
||||
segs.push(".");
|
||||
segs.push(seg);
|
||||
}
|
||||
}
|
||||
return segs.join("");
|
||||
}
|
||||
function prettifyError(error) {
|
||||
const lines = [];
|
||||
// sort by path length
|
||||
const issues = [...error.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
|
||||
// Process each issue
|
||||
for (const issue of issues) {
|
||||
lines.push(`✖ ${issue.message}`);
|
||||
if (issue.path?.length)
|
||||
lines.push(` → at ${toDotPath(issue.path)}`);
|
||||
}
|
||||
// Convert Map to formatted string
|
||||
return lines.join("\n");
|
||||
}
|
||||
@@ -0,0 +1,654 @@
|
||||
/**
|
||||
* @fileoverview Rule to enforce concise object methods and properties.
|
||||
* @author Jamund Ferguson
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const OPTIONS = {
|
||||
always: "always",
|
||||
never: "never",
|
||||
methods: "methods",
|
||||
properties: "properties",
|
||||
consistent: "consistent",
|
||||
consistentAsNeeded: "consistent-as-needed",
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
const CTOR_PREFIX_REGEX = /[^_$0-9]/u;
|
||||
const JSDOC_COMMENT_REGEX = /^\s*\*/u;
|
||||
|
||||
/**
|
||||
* Determines if the first character of the name is a capital letter.
|
||||
* @param {string} name The name of the node to evaluate.
|
||||
* @returns {boolean} True if the first character of the property name is a capital letter, false if not.
|
||||
* @private
|
||||
*/
|
||||
function isConstructor(name) {
|
||||
const match = CTOR_PREFIX_REGEX.exec(name);
|
||||
|
||||
// Not a constructor if name has no characters apart from '_', '$' and digits e.g. '_', '$$', '_8'
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstChar = name.charAt(match.index);
|
||||
|
||||
return firstChar === firstChar.toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the property can have a shorthand form.
|
||||
* @param {ASTNode} property Property AST node
|
||||
* @returns {boolean} True if the property can have a shorthand form
|
||||
* @private
|
||||
*/
|
||||
function canHaveShorthand(property) {
|
||||
return (
|
||||
property.kind !== "set" &&
|
||||
property.kind !== "get" &&
|
||||
property.type !== "SpreadElement" &&
|
||||
property.type !== "SpreadProperty" &&
|
||||
property.type !== "ExperimentalSpreadProperty"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a node is a string literal.
|
||||
* @param {ASTNode} node Any AST node.
|
||||
* @returns {boolean} `true` if it is a string literal.
|
||||
*/
|
||||
function isStringLiteral(node) {
|
||||
return node.type === "Literal" && typeof node.value === "string";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the property is a shorthand or not.
|
||||
* @param {ASTNode} property Property AST node
|
||||
* @returns {boolean} True if the property is considered shorthand, false if not.
|
||||
* @private
|
||||
*/
|
||||
function isShorthand(property) {
|
||||
// property.method is true when `{a(){}}`.
|
||||
return property.shorthand || property.method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the property's key and method or value are named equally.
|
||||
* @param {ASTNode} property Property AST node
|
||||
* @returns {boolean} True if the key and value are named equally, false if not.
|
||||
* @private
|
||||
*/
|
||||
function isRedundant(property) {
|
||||
const value = property.value;
|
||||
|
||||
if (value.type === "FunctionExpression") {
|
||||
return !value.id; // Only anonymous should be shorthand method.
|
||||
}
|
||||
if (value.type === "Identifier") {
|
||||
return astUtils.getStaticPropertyName(property) === value.name;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Require or disallow method and property shorthand syntax for object literals",
|
||||
recommended: false,
|
||||
frozen: true,
|
||||
url: "https://eslint.org/docs/latest/rules/object-shorthand",
|
||||
},
|
||||
|
||||
fixable: "code",
|
||||
|
||||
schema: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: [
|
||||
"always",
|
||||
"methods",
|
||||
"properties",
|
||||
"never",
|
||||
"consistent",
|
||||
"consistent-as-needed",
|
||||
],
|
||||
},
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 1,
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: ["always", "methods", "properties"],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
avoidQuotes: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 2,
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: ["always", "methods"],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
ignoreConstructors: {
|
||||
type: "boolean",
|
||||
},
|
||||
methodsIgnorePattern: {
|
||||
type: "string",
|
||||
},
|
||||
avoidQuotes: {
|
||||
type: "boolean",
|
||||
},
|
||||
avoidExplicitReturnArrows: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
defaultOptions: ["always"],
|
||||
|
||||
messages: {
|
||||
expectedAllPropertiesShorthanded:
|
||||
"Expected shorthand for all properties.",
|
||||
expectedLiteralMethodLongform:
|
||||
"Expected longform method syntax for string literal keys.",
|
||||
expectedPropertyShorthand: "Expected property shorthand.",
|
||||
expectedPropertyLongform: "Expected longform property syntax.",
|
||||
expectedMethodShorthand: "Expected method shorthand.",
|
||||
expectedMethodLongform: "Expected longform method syntax.",
|
||||
unexpectedMix:
|
||||
"Unexpected mix of shorthand and non-shorthand properties.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const APPLY = context.options[0];
|
||||
const APPLY_TO_METHODS =
|
||||
APPLY === OPTIONS.methods || APPLY === OPTIONS.always;
|
||||
const APPLY_TO_PROPS =
|
||||
APPLY === OPTIONS.properties || APPLY === OPTIONS.always;
|
||||
const APPLY_NEVER = APPLY === OPTIONS.never;
|
||||
const APPLY_CONSISTENT = APPLY === OPTIONS.consistent;
|
||||
const APPLY_CONSISTENT_AS_NEEDED = APPLY === OPTIONS.consistentAsNeeded;
|
||||
|
||||
const PARAMS = context.options[1] || {};
|
||||
const IGNORE_CONSTRUCTORS = PARAMS.ignoreConstructors;
|
||||
const METHODS_IGNORE_PATTERN = PARAMS.methodsIgnorePattern
|
||||
? new RegExp(PARAMS.methodsIgnorePattern, "u")
|
||||
: null;
|
||||
const AVOID_QUOTES = PARAMS.avoidQuotes;
|
||||
const AVOID_EXPLICIT_RETURN_ARROWS = !!PARAMS.avoidExplicitReturnArrows;
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
/**
|
||||
* Ensures that an object's properties are consistently shorthand, or not shorthand at all.
|
||||
* @param {ASTNode} node Property AST node
|
||||
* @param {boolean} checkRedundancy Whether to check longform redundancy
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkConsistency(node, checkRedundancy) {
|
||||
// We are excluding getters/setters and spread properties as they are considered neither longform nor shorthand.
|
||||
const properties = node.properties.filter(canHaveShorthand);
|
||||
|
||||
// Do we still have properties left after filtering the getters and setters?
|
||||
if (properties.length > 0) {
|
||||
const shorthandProperties = properties.filter(isShorthand);
|
||||
|
||||
/*
|
||||
* If we do not have an equal number of longform properties as
|
||||
* shorthand properties, we are using the annotations inconsistently
|
||||
*/
|
||||
if (shorthandProperties.length !== properties.length) {
|
||||
// We have at least 1 shorthand property
|
||||
if (shorthandProperties.length > 0) {
|
||||
context.report({ node, messageId: "unexpectedMix" });
|
||||
} else if (checkRedundancy) {
|
||||
/*
|
||||
* If all properties of the object contain a method or value with a name matching it's key,
|
||||
* all the keys are redundant.
|
||||
*/
|
||||
const canAlwaysUseShorthand =
|
||||
properties.every(isRedundant);
|
||||
|
||||
if (canAlwaysUseShorthand) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "expectedAllPropertiesShorthanded",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes a FunctionExpression node by making it into a shorthand property.
|
||||
* @param {SourceCodeFixer} fixer The fixer object
|
||||
* @param {ASTNode} node A `Property` node that has a `FunctionExpression` or `ArrowFunctionExpression` as its value
|
||||
* @returns {Object} A fix for this node
|
||||
*/
|
||||
function makeFunctionShorthand(fixer, node) {
|
||||
const firstKeyToken = node.computed
|
||||
? sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken)
|
||||
: sourceCode.getFirstToken(node.key);
|
||||
const lastKeyToken = node.computed
|
||||
? sourceCode.getFirstTokenBetween(
|
||||
node.key,
|
||||
node.value,
|
||||
astUtils.isClosingBracketToken,
|
||||
)
|
||||
: sourceCode.getLastToken(node.key);
|
||||
const keyText = sourceCode.text.slice(
|
||||
firstKeyToken.range[0],
|
||||
lastKeyToken.range[1],
|
||||
);
|
||||
let keyPrefix = "";
|
||||
|
||||
// key: /* */ () => {}
|
||||
if (sourceCode.commentsExistBetween(lastKeyToken, node.value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node.value.async) {
|
||||
keyPrefix += "async ";
|
||||
}
|
||||
if (node.value.generator) {
|
||||
keyPrefix += "*";
|
||||
}
|
||||
|
||||
const fixRange = [firstKeyToken.range[0], node.range[1]];
|
||||
const methodPrefix = keyPrefix + keyText;
|
||||
|
||||
if (node.value.type === "FunctionExpression") {
|
||||
const functionToken = sourceCode
|
||||
.getTokens(node.value)
|
||||
.find(
|
||||
token =>
|
||||
token.type === "Keyword" &&
|
||||
token.value === "function",
|
||||
);
|
||||
const tokenBeforeParams = node.value.generator
|
||||
? sourceCode.getTokenAfter(functionToken)
|
||||
: functionToken;
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
fixRange,
|
||||
methodPrefix +
|
||||
sourceCode.text.slice(
|
||||
tokenBeforeParams.range[1],
|
||||
node.value.range[1],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
const arrowToken = sourceCode.getTokenBefore(
|
||||
node.value.body,
|
||||
astUtils.isArrowToken,
|
||||
);
|
||||
const fnBody = sourceCode.text.slice(
|
||||
arrowToken.range[1],
|
||||
node.value.range[1],
|
||||
);
|
||||
|
||||
// First token should not be `async`
|
||||
const firstValueToken = sourceCode.getFirstToken(node.value, {
|
||||
skip: node.value.async ? 1 : 0,
|
||||
});
|
||||
|
||||
const sliceStart = firstValueToken.range[0];
|
||||
const sliceEnd = sourceCode.getTokenBefore(arrowToken).range[1];
|
||||
const shouldAddParens =
|
||||
node.value.params.length === 1 &&
|
||||
node.value.params[0].range[0] === sliceStart;
|
||||
|
||||
const oldParamText = sourceCode.text.slice(sliceStart, sliceEnd);
|
||||
const newParamText = shouldAddParens
|
||||
? `(${oldParamText})`
|
||||
: oldParamText;
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
fixRange,
|
||||
methodPrefix + newParamText + fnBody,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes a FunctionExpression node by making it into a longform property.
|
||||
* @param {SourceCodeFixer} fixer The fixer object
|
||||
* @param {ASTNode} node A `Property` node that has a `FunctionExpression` as its value
|
||||
* @returns {Object} A fix for this node
|
||||
*/
|
||||
function makeFunctionLongform(fixer, node) {
|
||||
const firstKeyToken = node.computed
|
||||
? sourceCode.getTokens(node).find(token => token.value === "[")
|
||||
: sourceCode.getFirstToken(node.key);
|
||||
const lastKeyToken = node.computed
|
||||
? sourceCode
|
||||
.getTokensBetween(node.key, node.value)
|
||||
.find(token => token.value === "]")
|
||||
: sourceCode.getLastToken(node.key);
|
||||
const keyText = sourceCode.text.slice(
|
||||
firstKeyToken.range[0],
|
||||
lastKeyToken.range[1],
|
||||
);
|
||||
let functionHeader = "function";
|
||||
|
||||
if (node.value.async) {
|
||||
functionHeader = `async ${functionHeader}`;
|
||||
}
|
||||
if (node.value.generator) {
|
||||
functionHeader = `${functionHeader}*`;
|
||||
}
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
[node.range[0], lastKeyToken.range[1]],
|
||||
`${keyText}: ${functionHeader}`,
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* To determine whether a given arrow function has a lexical identifier (`this`, `arguments`, `super`, or `new.target`),
|
||||
* create a stack of functions that define these identifiers (i.e. all functions except arrow functions) as the AST is
|
||||
* traversed. Whenever a new function is encountered, create a new entry on the stack (corresponding to a different lexical
|
||||
* scope of `this`), and whenever a function is exited, pop that entry off the stack. When an arrow function is entered,
|
||||
* keep a reference to it on the current stack entry, and remove that reference when the arrow function is exited.
|
||||
* When a lexical identifier is encountered, mark all the arrow functions on the current stack entry by adding them
|
||||
* to an `arrowsWithLexicalIdentifiers` set. Any arrow function in that set will not be reported by this rule,
|
||||
* because converting it into a method would change the value of one of the lexical identifiers.
|
||||
*/
|
||||
const lexicalScopeStack = [];
|
||||
const arrowsWithLexicalIdentifiers = new WeakSet();
|
||||
const argumentsIdentifiers = new WeakSet();
|
||||
|
||||
/**
|
||||
* Enters a function. This creates a new lexical identifier scope, so a new Set of arrow functions is pushed onto the stack.
|
||||
* Also, this marks all `arguments` identifiers so that they can be detected later.
|
||||
* @param {ASTNode} node The node representing the function.
|
||||
* @returns {void}
|
||||
*/
|
||||
function enterFunction(node) {
|
||||
lexicalScopeStack.unshift(new Set());
|
||||
sourceCode
|
||||
.getScope(node)
|
||||
.variables.filter(variable => variable.name === "arguments")
|
||||
.forEach(variable => {
|
||||
variable.references
|
||||
.map(ref => ref.identifier)
|
||||
.forEach(identifier =>
|
||||
argumentsIdentifiers.add(identifier),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Exits a function. This pops the current set of arrow functions off the lexical scope stack.
|
||||
* @returns {void}
|
||||
*/
|
||||
function exitFunction() {
|
||||
lexicalScopeStack.shift();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the current function as having a lexical keyword. This implies that all arrow functions
|
||||
* in the current lexical scope contain a reference to this lexical keyword.
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportLexicalIdentifier() {
|
||||
lexicalScopeStack[0].forEach(arrowFunction =>
|
||||
arrowsWithLexicalIdentifiers.add(arrowFunction),
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
Program: enterFunction,
|
||||
FunctionDeclaration: enterFunction,
|
||||
FunctionExpression: enterFunction,
|
||||
"Program:exit": exitFunction,
|
||||
"FunctionDeclaration:exit": exitFunction,
|
||||
"FunctionExpression:exit": exitFunction,
|
||||
|
||||
ArrowFunctionExpression(node) {
|
||||
lexicalScopeStack[0].add(node);
|
||||
},
|
||||
"ArrowFunctionExpression:exit"(node) {
|
||||
lexicalScopeStack[0].delete(node);
|
||||
},
|
||||
|
||||
ThisExpression: reportLexicalIdentifier,
|
||||
Super: reportLexicalIdentifier,
|
||||
MetaProperty(node) {
|
||||
if (
|
||||
node.meta.name === "new" &&
|
||||
node.property.name === "target"
|
||||
) {
|
||||
reportLexicalIdentifier();
|
||||
}
|
||||
},
|
||||
Identifier(node) {
|
||||
if (argumentsIdentifiers.has(node)) {
|
||||
reportLexicalIdentifier();
|
||||
}
|
||||
},
|
||||
|
||||
ObjectExpression(node) {
|
||||
if (APPLY_CONSISTENT) {
|
||||
checkConsistency(node, false);
|
||||
} else if (APPLY_CONSISTENT_AS_NEEDED) {
|
||||
checkConsistency(node, true);
|
||||
}
|
||||
},
|
||||
|
||||
"Property:exit"(node) {
|
||||
const isConciseProperty = node.method || node.shorthand;
|
||||
|
||||
// Ignore destructuring assignment
|
||||
if (node.parent.type === "ObjectPattern") {
|
||||
return;
|
||||
}
|
||||
|
||||
// getters and setters are ignored
|
||||
if (node.kind === "get" || node.kind === "set") {
|
||||
return;
|
||||
}
|
||||
|
||||
// only computed methods can fail the following checks
|
||||
if (
|
||||
node.computed &&
|
||||
node.value.type !== "FunctionExpression" &&
|
||||
node.value.type !== "ArrowFunctionExpression"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Checks for property/method shorthand.
|
||||
if (isConciseProperty) {
|
||||
if (
|
||||
node.method &&
|
||||
(APPLY_NEVER ||
|
||||
(AVOID_QUOTES && isStringLiteral(node.key)))
|
||||
) {
|
||||
const messageId = APPLY_NEVER
|
||||
? "expectedMethodLongform"
|
||||
: "expectedLiteralMethodLongform";
|
||||
|
||||
// { x() {} } should be written as { x: function() {} }
|
||||
context.report({
|
||||
node,
|
||||
messageId,
|
||||
fix: fixer => makeFunctionLongform(fixer, node),
|
||||
});
|
||||
} else if (APPLY_NEVER) {
|
||||
// { x } should be written as { x: x }
|
||||
context.report({
|
||||
node,
|
||||
messageId: "expectedPropertyLongform",
|
||||
fix: fixer =>
|
||||
fixer.insertTextAfter(
|
||||
node.key,
|
||||
`: ${node.key.name}`,
|
||||
),
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
APPLY_TO_METHODS &&
|
||||
!node.value.id &&
|
||||
(node.value.type === "FunctionExpression" ||
|
||||
node.value.type === "ArrowFunctionExpression")
|
||||
) {
|
||||
if (
|
||||
IGNORE_CONSTRUCTORS &&
|
||||
node.key.type === "Identifier" &&
|
||||
isConstructor(node.key.name)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (METHODS_IGNORE_PATTERN) {
|
||||
const propertyName =
|
||||
astUtils.getStaticPropertyName(node);
|
||||
|
||||
if (
|
||||
propertyName !== null &&
|
||||
METHODS_IGNORE_PATTERN.test(propertyName)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (AVOID_QUOTES && isStringLiteral(node.key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// {[x]: function(){}} should be written as {[x]() {}}
|
||||
if (
|
||||
node.value.type === "FunctionExpression" ||
|
||||
(node.value.type === "ArrowFunctionExpression" &&
|
||||
node.value.body.type === "BlockStatement" &&
|
||||
AVOID_EXPLICIT_RETURN_ARROWS &&
|
||||
!arrowsWithLexicalIdentifiers.has(node.value))
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "expectedMethodShorthand",
|
||||
fix: fixer => makeFunctionShorthand(fixer, node),
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
node.value.type === "Identifier" &&
|
||||
node.key.name === node.value.name &&
|
||||
APPLY_TO_PROPS
|
||||
) {
|
||||
// Skip if there are JSDoc comments inside the property (e.g., JSDoc type annotations)
|
||||
const comments = sourceCode.getCommentsInside(node);
|
||||
if (
|
||||
comments.some(
|
||||
comment =>
|
||||
comment.type === "Block" &&
|
||||
JSDOC_COMMENT_REGEX.test(comment.value) &&
|
||||
comment.value.includes("@type"),
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// {x: x} should be written as {x}
|
||||
context.report({
|
||||
node,
|
||||
messageId: "expectedPropertyShorthand",
|
||||
fix(fixer) {
|
||||
// x: /* */ x
|
||||
// x: (/* */ x)
|
||||
if (sourceCode.getCommentsInside(node).length > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.replaceText(node, node.value.name);
|
||||
},
|
||||
});
|
||||
} else if (
|
||||
node.value.type === "Identifier" &&
|
||||
node.key.type === "Literal" &&
|
||||
node.key.value === node.value.name &&
|
||||
APPLY_TO_PROPS
|
||||
) {
|
||||
if (AVOID_QUOTES) {
|
||||
return;
|
||||
}
|
||||
|
||||
const comments = sourceCode.getCommentsInside(node);
|
||||
if (
|
||||
comments.some(
|
||||
comment =>
|
||||
comment.type === "Block" &&
|
||||
comment.value.startsWith("*") &&
|
||||
comment.value.includes("@type"),
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// {"x": x} should be written as {x}
|
||||
context.report({
|
||||
node,
|
||||
messageId: "expectedPropertyShorthand",
|
||||
fix(fixer) {
|
||||
// "x": /* */ x
|
||||
// "x": (/* */ x)
|
||||
if (sourceCode.getCommentsInside(node).length > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.replaceText(node, node.value.name);
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
import * as ts from 'typescript';
|
||||
/**
|
||||
* @deprecated
|
||||
* Gets the source file for a given node
|
||||
*/
|
||||
export declare function getSourceFileOfNode(node: ts.Node): ts.SourceFile;
|
||||
@@ -0,0 +1 @@
|
||||
12345
|
||||
@@ -0,0 +1,306 @@
|
||||
/**
|
||||
* @fileoverview Translates tokens between Acorn format and Esprima format.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/**
|
||||
* @import * as acorn from "acorn";
|
||||
* @import { EnhancedTokTypes } from "./espree.js"
|
||||
* @import { NormalizedEcmaVersion } from "./options.js";
|
||||
* @import { EspreeToken as EsprimaToken } from "../espree.js";
|
||||
*/
|
||||
/**
|
||||
* Based on the `acorn.Token` class, but without a fixed `type` (since we need
|
||||
* it to be a string). Avoiding `type` lets us make one extending interface
|
||||
* more strict and another more lax.
|
||||
*
|
||||
* We could make `value` more strict to `string` even though the original is
|
||||
* `any`.
|
||||
*
|
||||
* `start` and `end` are required in `acorn.Token`
|
||||
*
|
||||
* `loc` and `range` are from `acorn.Token`
|
||||
*
|
||||
* Adds `regex`.
|
||||
*/
|
||||
/**
|
||||
* @typedef {{
|
||||
* jsxAttrValueToken: boolean;
|
||||
* ecmaVersion: NormalizedEcmaVersion;
|
||||
* }} ExtraNoTokens
|
||||
* @typedef {{
|
||||
* tokens: EsprimaToken[]
|
||||
* } & ExtraNoTokens} Extra
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Esprima Token Types
|
||||
const Token = {
|
||||
Boolean: "Boolean",
|
||||
EOF: "<end>",
|
||||
Identifier: "Identifier",
|
||||
PrivateIdentifier: "PrivateIdentifier",
|
||||
Keyword: "Keyword",
|
||||
Null: "Null",
|
||||
Numeric: "Numeric",
|
||||
Punctuator: "Punctuator",
|
||||
String: "String",
|
||||
RegularExpression: "RegularExpression",
|
||||
Template: "Template",
|
||||
JSXIdentifier: "JSXIdentifier",
|
||||
JSXText: "JSXText",
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts part of a template into an Esprima token.
|
||||
* @param {acorn.Token[]} tokens The Acorn tokens representing the template.
|
||||
* @param {string} code The source code.
|
||||
* @returns {EsprimaToken} The Esprima equivalent of the template token.
|
||||
* @private
|
||||
*/
|
||||
function convertTemplatePart(tokens, code) {
|
||||
const firstToken = tokens[0],
|
||||
lastTemplateToken =
|
||||
/** @type {acorn.Token & { loc: acorn.SourceLocation, range: [number, number] }} */ (
|
||||
tokens.at(-1)
|
||||
);
|
||||
|
||||
/** @type {EsprimaToken} */
|
||||
const token = {
|
||||
type: Token.Template,
|
||||
value: code.slice(firstToken.start, lastTemplateToken.end),
|
||||
};
|
||||
|
||||
if (firstToken.loc) {
|
||||
token.loc = {
|
||||
start: firstToken.loc.start,
|
||||
end: lastTemplateToken.loc.end,
|
||||
};
|
||||
}
|
||||
|
||||
if (firstToken.range) {
|
||||
token.start = firstToken.range[0];
|
||||
token.end = lastTemplateToken.range[1];
|
||||
token.range = [token.start, token.end];
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/* eslint-disable jsdoc/check-types -- The API allows either */
|
||||
/**
|
||||
* Contains logic to translate Acorn tokens into Esprima tokens.
|
||||
*/
|
||||
class TokenTranslator {
|
||||
/**
|
||||
* Contains logic to translate Acorn tokens into Esprima tokens.
|
||||
* @param {EnhancedTokTypes} acornTokTypes The Acorn token types.
|
||||
* @param {string|String} code The source code Acorn is parsing. This is necessary
|
||||
* to correct the "value" property of some tokens.
|
||||
*/
|
||||
constructor(acornTokTypes, code) {
|
||||
/* eslint-enable jsdoc/check-types -- The API allows either */
|
||||
|
||||
// token types
|
||||
this._acornTokTypes = acornTokTypes;
|
||||
|
||||
// token buffer for templates
|
||||
/** @type {acorn.Token[]} */
|
||||
this._tokens = [];
|
||||
|
||||
// track the last curly brace
|
||||
this._curlyBrace = null;
|
||||
|
||||
// the source code
|
||||
this._code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a single Esprima token to a single Acorn token. This may be
|
||||
* inaccurate due to how templates are handled differently in Esprima and
|
||||
* Acorn, but should be accurate for all other tokens.
|
||||
* @param {acorn.Token} token The Acorn token to translate.
|
||||
* @param {ExtraNoTokens} extra Espree extra object.
|
||||
* @returns {EsprimaToken} The Esprima version of the token.
|
||||
*/
|
||||
translate(token, extra) {
|
||||
const type = token.type,
|
||||
tt = this._acornTokTypes,
|
||||
// We use an unknown type because `acorn.Token` is a class whose
|
||||
// `type` property we cannot override to our desired `string`;
|
||||
// this also allows us to define a stricter `EsprimaToken` with
|
||||
// a string-only `type` property
|
||||
unknownTokenType = /** @type {unknown} */ (token),
|
||||
newToken = /** @type {EsprimaToken} */ (unknownTokenType);
|
||||
|
||||
if (type === tt.name) {
|
||||
newToken.type = Token.Identifier;
|
||||
|
||||
// TODO: See if this is an Acorn bug
|
||||
if ("value" in token && token.value === "static") {
|
||||
newToken.type = Token.Keyword;
|
||||
}
|
||||
|
||||
if (
|
||||
extra.ecmaVersion > 5 &&
|
||||
"value" in token &&
|
||||
(token.value === "yield" || token.value === "let")
|
||||
) {
|
||||
newToken.type = Token.Keyword;
|
||||
}
|
||||
} else if (type === tt.privateId) {
|
||||
newToken.type = Token.PrivateIdentifier;
|
||||
} else if (
|
||||
type === tt.semi ||
|
||||
type === tt.comma ||
|
||||
type === tt.parenL ||
|
||||
type === tt.parenR ||
|
||||
type === tt.braceL ||
|
||||
type === tt.braceR ||
|
||||
type === tt.dot ||
|
||||
type === tt.bracketL ||
|
||||
type === tt.colon ||
|
||||
type === tt.question ||
|
||||
type === tt.bracketR ||
|
||||
type === tt.ellipsis ||
|
||||
type === tt.arrow ||
|
||||
type === tt.jsxTagStart ||
|
||||
type === tt.incDec ||
|
||||
type === tt.starstar ||
|
||||
type === tt.jsxTagEnd ||
|
||||
type === tt.prefix ||
|
||||
type === tt.questionDot ||
|
||||
("binop" in type && type.binop && !type.keyword) ||
|
||||
("isAssign" in type && type.isAssign)
|
||||
) {
|
||||
newToken.type = Token.Punctuator;
|
||||
newToken.value = this._code.slice(token.start, token.end);
|
||||
} else if (type === tt.jsxName) {
|
||||
newToken.type = Token.JSXIdentifier;
|
||||
} else if (type.label === "jsxText" || type === tt.jsxAttrValueToken) {
|
||||
newToken.type = Token.JSXText;
|
||||
} else if (type.keyword) {
|
||||
if (type.keyword === "true" || type.keyword === "false") {
|
||||
newToken.type = Token.Boolean;
|
||||
} else if (type.keyword === "null") {
|
||||
newToken.type = Token.Null;
|
||||
} else {
|
||||
newToken.type = Token.Keyword;
|
||||
}
|
||||
} else if (type === tt.num) {
|
||||
newToken.type = Token.Numeric;
|
||||
newToken.value = this._code.slice(token.start, token.end);
|
||||
} else if (type === tt.string) {
|
||||
if (extra.jsxAttrValueToken) {
|
||||
extra.jsxAttrValueToken = false;
|
||||
newToken.type = Token.JSXText;
|
||||
} else {
|
||||
newToken.type = Token.String;
|
||||
}
|
||||
|
||||
newToken.value = this._code.slice(token.start, token.end);
|
||||
} else if (type === tt.regexp) {
|
||||
newToken.type = Token.RegularExpression;
|
||||
const value = /** @type {{flags: string, pattern: string}} */ (
|
||||
"value" in token && token.value
|
||||
);
|
||||
|
||||
newToken.regex = {
|
||||
flags: value.flags,
|
||||
pattern: value.pattern,
|
||||
};
|
||||
newToken.value = `/${value.pattern}/${value.flags}`;
|
||||
}
|
||||
|
||||
return newToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to call during Acorn's onToken handler.
|
||||
* @param {acorn.Token} token The Acorn token.
|
||||
* @param {Extra} extra The Espree extra object.
|
||||
* @returns {void}
|
||||
*/
|
||||
onToken(token, extra) {
|
||||
const tt = this._acornTokTypes,
|
||||
tokens = extra.tokens,
|
||||
templateTokens = this._tokens;
|
||||
|
||||
/**
|
||||
* Flushes the buffered template tokens and resets the template
|
||||
* tracking.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
const translateTemplateTokens = () => {
|
||||
tokens.push(convertTemplatePart(this._tokens, this._code));
|
||||
this._tokens = [];
|
||||
};
|
||||
|
||||
if (token.type === tt.eof) {
|
||||
// might be one last curlyBrace
|
||||
if (this._curlyBrace) {
|
||||
tokens.push(this.translate(this._curlyBrace, extra));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.type === tt.backQuote) {
|
||||
// if there's already a curly, it's not part of the template
|
||||
if (this._curlyBrace) {
|
||||
tokens.push(this.translate(this._curlyBrace, extra));
|
||||
this._curlyBrace = null;
|
||||
}
|
||||
|
||||
templateTokens.push(token);
|
||||
|
||||
// it's the end
|
||||
if (templateTokens.length > 1) {
|
||||
translateTemplateTokens();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (token.type === tt.dollarBraceL) {
|
||||
templateTokens.push(token);
|
||||
translateTemplateTokens();
|
||||
return;
|
||||
}
|
||||
if (token.type === tt.braceR) {
|
||||
// if there's already a curly, it's not part of the template
|
||||
if (this._curlyBrace) {
|
||||
tokens.push(this.translate(this._curlyBrace, extra));
|
||||
}
|
||||
|
||||
// store new curly for later
|
||||
this._curlyBrace = token;
|
||||
return;
|
||||
}
|
||||
if (token.type === tt.template || token.type === tt.invalidTemplate) {
|
||||
if (this._curlyBrace) {
|
||||
templateTokens.push(this._curlyBrace);
|
||||
this._curlyBrace = null;
|
||||
}
|
||||
|
||||
templateTokens.push(token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._curlyBrace) {
|
||||
tokens.push(this.translate(this._curlyBrace, extra));
|
||||
this._curlyBrace = null;
|
||||
}
|
||||
|
||||
tokens.push(this.translate(token, extra));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export default TokenTranslator;
|
||||
@@ -0,0 +1,23 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference no-default-lib="true"/>
|
||||
|
||||
/// <reference lib="es2016" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="webworker.importscripts" />
|
||||
/// <reference lib="scripthost" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"pasta.js","sourceRoot":"","sources":["../src/pasta.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,KAAK,IAAI,EAAE,EAAE,MAAM,WAAW,CAAC;AACtD,kBAAkB;AAClB,MAAM,CAAC,MAAM,MAAM,GAAc,EAAE,CAAC;AACpC,kBAAkB;AAClB,MAAM,CAAC,MAAM,KAAK,GAAc,EAAE,CAAC"}
|
||||
Reference in New Issue
Block a user