WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import stringify from './stringify.js';
|
||||
import parse from './parse.js';
|
||||
|
||||
function stringToBytes(str) {
|
||||
str = unescape(encodeURIComponent(str)); // UTF8 escape
|
||||
|
||||
var bytes = [];
|
||||
|
||||
for (var i = 0; i < str.length; ++i) {
|
||||
bytes.push(str.charCodeAt(i));
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export var DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
|
||||
export var URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
|
||||
export default function (name, version, hashfunc) {
|
||||
function generateUUID(value, namespace, buf, offset) {
|
||||
if (typeof value === 'string') {
|
||||
value = stringToBytes(value);
|
||||
}
|
||||
|
||||
if (typeof namespace === 'string') {
|
||||
namespace = parse(namespace);
|
||||
}
|
||||
|
||||
if (namespace.length !== 16) {
|
||||
throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)');
|
||||
} // Compute hash of namespace and value, Per 4.3
|
||||
// Future: Use spread syntax when supported on all platforms, e.g. `bytes =
|
||||
// hashfunc([...namespace, ... value])`
|
||||
|
||||
|
||||
var bytes = new Uint8Array(16 + value.length);
|
||||
bytes.set(namespace);
|
||||
bytes.set(value, namespace.length);
|
||||
bytes = hashfunc(bytes);
|
||||
bytes[6] = bytes[6] & 0x0f | version;
|
||||
bytes[8] = bytes[8] & 0x3f | 0x80;
|
||||
|
||||
if (buf) {
|
||||
offset = offset || 0;
|
||||
|
||||
for (var i = 0; i < 16; ++i) {
|
||||
buf[offset + i] = bytes[i];
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
return stringify(bytes);
|
||||
} // Function#name is not settable on some platforms (#270)
|
||||
|
||||
|
||||
try {
|
||||
generateUUID.name = name; // eslint-disable-next-line no-empty
|
||||
} catch (err) {} // For CommonJS default export support
|
||||
|
||||
|
||||
generateUUID.DNS = DNS;
|
||||
generateUUID.URL = URL;
|
||||
return generateUUID;
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.blake3 = exports.BLAKE3 = void 0;
|
||||
/**
|
||||
* Blake3 fast hash is Blake2 with reduced security (round count). Can also be used as MAC & KDF.
|
||||
*
|
||||
* It is advertised as "the fastest cryptographic hash". However, it isn't true in JS.
|
||||
* Why is this so slow? While it should be 6x faster than blake2b, perf diff is only 20%:
|
||||
*
|
||||
* * There is only 30% reduction in number of rounds from blake2s
|
||||
* * Speed-up comes from tree structure, which is parallelized using SIMD & threading.
|
||||
* These features are not present in JS, so we only get overhead from trees.
|
||||
* * Parallelization only happens on 1024-byte chunks: there is no benefit for small inputs.
|
||||
* * It is still possible to make it faster using: a) loop unrolling b) web workers c) wasm
|
||||
* @module
|
||||
*/
|
||||
const _md_ts_1 = require("./_md.js");
|
||||
const _u64_ts_1 = require("./_u64.js");
|
||||
const blake2_ts_1 = require("./blake2.js");
|
||||
// prettier-ignore
|
||||
const utils_ts_1 = require("./utils.js");
|
||||
// Flag bitset
|
||||
const B3_Flags = {
|
||||
CHUNK_START: 0b1,
|
||||
CHUNK_END: 0b10,
|
||||
PARENT: 0b100,
|
||||
ROOT: 0b1000,
|
||||
KEYED_HASH: 0b10000,
|
||||
DERIVE_KEY_CONTEXT: 0b100000,
|
||||
DERIVE_KEY_MATERIAL: 0b1000000,
|
||||
};
|
||||
const B3_IV = _md_ts_1.SHA256_IV.slice();
|
||||
const B3_SIGMA = /* @__PURE__ */ (() => {
|
||||
const Id = Array.from({ length: 16 }, (_, i) => i);
|
||||
const permute = (arr) => [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8].map((i) => arr[i]);
|
||||
const res = [];
|
||||
for (let i = 0, v = Id; i < 7; i++, v = permute(v))
|
||||
res.push(...v);
|
||||
return Uint8Array.from(res);
|
||||
})();
|
||||
/** Blake3 hash. Can be used as MAC and KDF. */
|
||||
class BLAKE3 extends blake2_ts_1.BLAKE2 {
|
||||
constructor(opts = {}, flags = 0) {
|
||||
super(64, opts.dkLen === undefined ? 32 : opts.dkLen);
|
||||
this.chunkPos = 0; // Position of current block in chunk
|
||||
this.chunksDone = 0; // How many chunks we already have
|
||||
this.flags = 0 | 0;
|
||||
this.stack = [];
|
||||
// Output
|
||||
this.posOut = 0;
|
||||
this.bufferOut32 = new Uint32Array(16);
|
||||
this.chunkOut = 0; // index of output chunk
|
||||
this.enableXOF = true;
|
||||
const { key, context } = opts;
|
||||
const hasContext = context !== undefined;
|
||||
if (key !== undefined) {
|
||||
if (hasContext)
|
||||
throw new Error('Only "key" or "context" can be specified at same time');
|
||||
const k = (0, utils_ts_1.toBytes)(key).slice();
|
||||
(0, utils_ts_1.abytes)(k, 32);
|
||||
this.IV = (0, utils_ts_1.u32)(k);
|
||||
(0, utils_ts_1.swap32IfBE)(this.IV);
|
||||
this.flags = flags | B3_Flags.KEYED_HASH;
|
||||
}
|
||||
else if (hasContext) {
|
||||
const ctx = (0, utils_ts_1.toBytes)(context);
|
||||
const contextKey = new BLAKE3({ dkLen: 32 }, B3_Flags.DERIVE_KEY_CONTEXT)
|
||||
.update(ctx)
|
||||
.digest();
|
||||
this.IV = (0, utils_ts_1.u32)(contextKey);
|
||||
(0, utils_ts_1.swap32IfBE)(this.IV);
|
||||
this.flags = flags | B3_Flags.DERIVE_KEY_MATERIAL;
|
||||
}
|
||||
else {
|
||||
this.IV = B3_IV.slice();
|
||||
this.flags = flags;
|
||||
}
|
||||
this.state = this.IV.slice();
|
||||
this.bufferOut = (0, utils_ts_1.u8)(this.bufferOut32);
|
||||
}
|
||||
// Unused
|
||||
get() {
|
||||
return [];
|
||||
}
|
||||
set() { }
|
||||
b2Compress(counter, flags, buf, bufPos = 0) {
|
||||
const { state: s, pos } = this;
|
||||
const { h, l } = (0, _u64_ts_1.fromBig)(BigInt(counter), true);
|
||||
// prettier-ignore
|
||||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = (0, blake2_ts_1.compress)(B3_SIGMA, bufPos, buf, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], B3_IV[0], B3_IV[1], B3_IV[2], B3_IV[3], h, l, pos, flags);
|
||||
s[0] = v0 ^ v8;
|
||||
s[1] = v1 ^ v9;
|
||||
s[2] = v2 ^ v10;
|
||||
s[3] = v3 ^ v11;
|
||||
s[4] = v4 ^ v12;
|
||||
s[5] = v5 ^ v13;
|
||||
s[6] = v6 ^ v14;
|
||||
s[7] = v7 ^ v15;
|
||||
}
|
||||
compress(buf, bufPos = 0, isLast = false) {
|
||||
// Compress last block
|
||||
let flags = this.flags;
|
||||
if (!this.chunkPos)
|
||||
flags |= B3_Flags.CHUNK_START;
|
||||
if (this.chunkPos === 15 || isLast)
|
||||
flags |= B3_Flags.CHUNK_END;
|
||||
if (!isLast)
|
||||
this.pos = this.blockLen;
|
||||
this.b2Compress(this.chunksDone, flags, buf, bufPos);
|
||||
this.chunkPos += 1;
|
||||
// If current block is last in chunk (16 blocks), then compress chunks
|
||||
if (this.chunkPos === 16 || isLast) {
|
||||
let chunk = this.state;
|
||||
this.state = this.IV.slice();
|
||||
// If not the last one, compress only when there are trailing zeros in chunk counter
|
||||
// chunks used as binary tree where current stack is path. Zero means current leaf is finished and can be compressed.
|
||||
// 1 (001) - leaf not finished (just push current chunk to stack)
|
||||
// 2 (010) - leaf finished at depth=1 (merge with last elm on stack and push back)
|
||||
// 3 (011) - last leaf not finished
|
||||
// 4 (100) - leafs finished at depth=1 and depth=2
|
||||
for (let last, chunks = this.chunksDone + 1; isLast || !(chunks & 1); chunks >>= 1) {
|
||||
if (!(last = this.stack.pop()))
|
||||
break;
|
||||
this.buffer32.set(last, 0);
|
||||
this.buffer32.set(chunk, 8);
|
||||
this.pos = this.blockLen;
|
||||
this.b2Compress(0, this.flags | B3_Flags.PARENT, this.buffer32, 0);
|
||||
chunk = this.state;
|
||||
this.state = this.IV.slice();
|
||||
}
|
||||
this.chunksDone++;
|
||||
this.chunkPos = 0;
|
||||
this.stack.push(chunk);
|
||||
}
|
||||
this.pos = 0;
|
||||
}
|
||||
_cloneInto(to) {
|
||||
to = super._cloneInto(to);
|
||||
const { IV, flags, state, chunkPos, posOut, chunkOut, stack, chunksDone } = this;
|
||||
to.state.set(state.slice());
|
||||
to.stack = stack.map((i) => Uint32Array.from(i));
|
||||
to.IV.set(IV);
|
||||
to.flags = flags;
|
||||
to.chunkPos = chunkPos;
|
||||
to.chunksDone = chunksDone;
|
||||
to.posOut = posOut;
|
||||
to.chunkOut = chunkOut;
|
||||
to.enableXOF = this.enableXOF;
|
||||
to.bufferOut32.set(this.bufferOut32);
|
||||
return to;
|
||||
}
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
(0, utils_ts_1.clean)(this.state, this.buffer32, this.IV, this.bufferOut32);
|
||||
(0, utils_ts_1.clean)(...this.stack);
|
||||
}
|
||||
// Same as b2Compress, but doesn't modify state and returns 16 u32 array (instead of 8)
|
||||
b2CompressOut() {
|
||||
const { state: s, pos, flags, buffer32, bufferOut32: out32 } = this;
|
||||
const { h, l } = (0, _u64_ts_1.fromBig)(BigInt(this.chunkOut++));
|
||||
(0, utils_ts_1.swap32IfBE)(buffer32);
|
||||
// prettier-ignore
|
||||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = (0, blake2_ts_1.compress)(B3_SIGMA, 0, buffer32, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], B3_IV[0], B3_IV[1], B3_IV[2], B3_IV[3], l, h, pos, flags);
|
||||
out32[0] = v0 ^ v8;
|
||||
out32[1] = v1 ^ v9;
|
||||
out32[2] = v2 ^ v10;
|
||||
out32[3] = v3 ^ v11;
|
||||
out32[4] = v4 ^ v12;
|
||||
out32[5] = v5 ^ v13;
|
||||
out32[6] = v6 ^ v14;
|
||||
out32[7] = v7 ^ v15;
|
||||
out32[8] = s[0] ^ v8;
|
||||
out32[9] = s[1] ^ v9;
|
||||
out32[10] = s[2] ^ v10;
|
||||
out32[11] = s[3] ^ v11;
|
||||
out32[12] = s[4] ^ v12;
|
||||
out32[13] = s[5] ^ v13;
|
||||
out32[14] = s[6] ^ v14;
|
||||
out32[15] = s[7] ^ v15;
|
||||
(0, utils_ts_1.swap32IfBE)(buffer32);
|
||||
(0, utils_ts_1.swap32IfBE)(out32);
|
||||
this.posOut = 0;
|
||||
}
|
||||
finish() {
|
||||
if (this.finished)
|
||||
return;
|
||||
this.finished = true;
|
||||
// Padding
|
||||
(0, utils_ts_1.clean)(this.buffer.subarray(this.pos));
|
||||
// Process last chunk
|
||||
let flags = this.flags | B3_Flags.ROOT;
|
||||
if (this.stack.length) {
|
||||
flags |= B3_Flags.PARENT;
|
||||
(0, utils_ts_1.swap32IfBE)(this.buffer32);
|
||||
this.compress(this.buffer32, 0, true);
|
||||
(0, utils_ts_1.swap32IfBE)(this.buffer32);
|
||||
this.chunksDone = 0;
|
||||
this.pos = this.blockLen;
|
||||
}
|
||||
else {
|
||||
flags |= (!this.chunkPos ? B3_Flags.CHUNK_START : 0) | B3_Flags.CHUNK_END;
|
||||
}
|
||||
this.flags = flags;
|
||||
this.b2CompressOut();
|
||||
}
|
||||
writeInto(out) {
|
||||
(0, utils_ts_1.aexists)(this, false);
|
||||
(0, utils_ts_1.abytes)(out);
|
||||
this.finish();
|
||||
const { blockLen, bufferOut } = this;
|
||||
for (let pos = 0, len = out.length; pos < len;) {
|
||||
if (this.posOut >= blockLen)
|
||||
this.b2CompressOut();
|
||||
const take = Math.min(blockLen - this.posOut, len - pos);
|
||||
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
|
||||
this.posOut += take;
|
||||
pos += take;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
xofInto(out) {
|
||||
if (!this.enableXOF)
|
||||
throw new Error('XOF is not possible after digest call');
|
||||
return this.writeInto(out);
|
||||
}
|
||||
xof(bytes) {
|
||||
(0, utils_ts_1.anumber)(bytes);
|
||||
return this.xofInto(new Uint8Array(bytes));
|
||||
}
|
||||
digestInto(out) {
|
||||
(0, utils_ts_1.aoutput)(out, this);
|
||||
if (this.finished)
|
||||
throw new Error('digest() was already called');
|
||||
this.enableXOF = false;
|
||||
this.writeInto(out);
|
||||
this.destroy();
|
||||
return out;
|
||||
}
|
||||
digest() {
|
||||
return this.digestInto(new Uint8Array(this.outputLen));
|
||||
}
|
||||
}
|
||||
exports.BLAKE3 = BLAKE3;
|
||||
/**
|
||||
* BLAKE3 hash function. Can be used as MAC and KDF.
|
||||
* @param msg - message that would be hashed
|
||||
* @param opts - `dkLen` for output length, `key` for MAC mode, `context` for KDF mode
|
||||
* @example
|
||||
* const data = new Uint8Array(32);
|
||||
* const hash = blake3(data);
|
||||
* const mac = blake3(data, { key: new Uint8Array(32) });
|
||||
* const kdf = blake3(data, { context: 'application name' });
|
||||
*/
|
||||
exports.blake3 = (0, utils_ts_1.createXOFer)((opts) => new BLAKE3(opts));
|
||||
//# sourceMappingURL=blake3.js.map
|
||||
@@ -0,0 +1,23 @@
|
||||
"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.es2015_collection = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2015_collection = {
|
||||
libs: [],
|
||||
variables: [
|
||||
['Map', base_config_1.TYPE_VALUE],
|
||||
['MapConstructor', base_config_1.TYPE],
|
||||
['ReadonlyMap', base_config_1.TYPE],
|
||||
['WeakMap', base_config_1.TYPE_VALUE],
|
||||
['WeakMapConstructor', base_config_1.TYPE],
|
||||
['Set', base_config_1.TYPE_VALUE],
|
||||
['SetConstructor', base_config_1.TYPE],
|
||||
['ReadonlySet', base_config_1.TYPE],
|
||||
['WeakSet', base_config_1.TYPE_VALUE],
|
||||
['WeakSetConstructor', base_config_1.TYPE],
|
||||
],
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
export declare var SymbolFlags: any;
|
||||
//# sourceMappingURL=symbolFlags.d.ts.map
|
||||
@@ -0,0 +1,173 @@
|
||||
# delay
|
||||
|
||||
> Delay a promise a specified amount of time
|
||||
|
||||
*If you target [Node.js 15](https://medium.com/@nodejs/node-js-v15-0-0-is-here-deb00750f278) or later, you can do `await require('timers/promises').setTimeout(1000)` instead.*
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install delay
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const delay = require('delay');
|
||||
|
||||
(async () => {
|
||||
bar();
|
||||
|
||||
await delay(100);
|
||||
|
||||
// Executed 100 milliseconds later
|
||||
baz();
|
||||
})();
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### delay(milliseconds, options?)
|
||||
|
||||
Create a promise which resolves after the specified `milliseconds`.
|
||||
|
||||
### delay.reject(milliseconds, options?)
|
||||
|
||||
Create a promise which rejects after the specified `milliseconds`.
|
||||
|
||||
### delay.range(minimum, maximum, options?)
|
||||
|
||||
Create a promise which resolves after a random amount of milliseconds between `minimum` and `maximum` has passed.
|
||||
|
||||
Useful for tests and web scraping since they can have unpredictable performance. For example, if you have a test that asserts a method should not take longer than a certain amount of time, and then run it on a CI, it could take longer. So with `.range()`, you could give it a threshold instead.
|
||||
|
||||
#### milliseconds
|
||||
#### mininum
|
||||
#### maximum
|
||||
|
||||
Type: `number`
|
||||
|
||||
Milliseconds to delay the promise.
|
||||
|
||||
#### options
|
||||
|
||||
Type: `object`
|
||||
|
||||
##### value
|
||||
|
||||
Type: `unknown`
|
||||
|
||||
Optional value to resolve or reject in the returned promise.
|
||||
|
||||
##### signal
|
||||
|
||||
Type: [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
|
||||
|
||||
The returned promise will be rejected with an AbortError if the signal is aborted. AbortSignal is available in all modern browsers and there is a [ponyfill for Node.js](https://github.com/mysticatea/abort-controller).
|
||||
|
||||
### delayPromise.clear()
|
||||
|
||||
Clears the delay and settles the promise.
|
||||
|
||||
### delay.createWithTimers({clearTimeout, setTimeout})
|
||||
|
||||
Creates a new `delay` instance using the provided functions for clearing and setting timeouts. Useful if you're about to stub timers globally, but you still want to use `delay` to manage your tests.
|
||||
|
||||
## Advanced usage
|
||||
|
||||
Passing a value:
|
||||
|
||||
```js
|
||||
const delay = require('delay');
|
||||
|
||||
(async() => {
|
||||
const result = await delay(100, {value: '🦄'});
|
||||
|
||||
// Executed after 100 milliseconds
|
||||
console.log(result);
|
||||
//=> '🦄'
|
||||
})();
|
||||
```
|
||||
|
||||
Using `delay.reject()`, which optionally accepts a value and rejects it `ms` later:
|
||||
|
||||
```js
|
||||
const delay = require('delay');
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
await delay.reject(100, {value: new Error('🦄')});
|
||||
|
||||
console.log('This is never executed');
|
||||
} catch (error) {
|
||||
// 100 milliseconds later
|
||||
console.log(error);
|
||||
//=> [Error: 🦄]
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
You can settle the delay early by calling `.clear()`:
|
||||
|
||||
```js
|
||||
const delay = require('delay');
|
||||
|
||||
(async () => {
|
||||
const delayedPromise = delay(1000, {value: 'Done'});
|
||||
|
||||
setTimeout(() => {
|
||||
delayedPromise.clear();
|
||||
}, 500);
|
||||
|
||||
// 500 milliseconds later
|
||||
console.log(await delayedPromise);
|
||||
//=> 'Done'
|
||||
})();
|
||||
```
|
||||
|
||||
You can abort the delay with an AbortSignal:
|
||||
|
||||
```js
|
||||
const delay = require('delay');
|
||||
|
||||
(async () => {
|
||||
const abortController = new AbortController();
|
||||
|
||||
setTimeout(() => {
|
||||
abortController.abort();
|
||||
}, 500);
|
||||
|
||||
try {
|
||||
await delay(1000, {signal: abortController.signal});
|
||||
} catch (error) {
|
||||
// 500 milliseconds later
|
||||
console.log(error.name)
|
||||
//=> 'AbortError'
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
Create a new instance that is unaffected by libraries such as [lolex](https://github.com/sinonjs/lolex/):
|
||||
|
||||
```js
|
||||
const delay = require('delay');
|
||||
|
||||
const customDelay = delay.createWithTimers({clearTimeout, setTimeout});
|
||||
|
||||
(async() => {
|
||||
const result = await customDelay(100, {value: '🦄'});
|
||||
|
||||
// Executed after 100 milliseconds
|
||||
console.log(result);
|
||||
//=> '🦄'
|
||||
})();
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [delay-cli](https://github.com/sindresorhus/delay-cli) - CLI for this module
|
||||
- [p-cancelable](https://github.com/sindresorhus/p-cancelable) - Create a promise that can be canceled
|
||||
- [p-min-delay](https://github.com/sindresorhus/p-min-delay) - Delay a promise a minimum amount of time
|
||||
- [p-immediate](https://github.com/sindresorhus/p-immediate) - Returns a promise resolved in the next event loop - think `setImmediate()`
|
||||
- [p-timeout](https://github.com/sindresorhus/p-timeout) - Timeout a promise after a specified amount of time
|
||||
- [More…](https://github.com/sindresorhus/promise-fun)
|
||||
@@ -0,0 +1,131 @@
|
||||
# fast-json-stable-stringify
|
||||
|
||||
Deterministic `JSON.stringify()` - a faster version of [@substack](https://github.com/substack)'s json-stable-strigify without [jsonify](https://github.com/substack/jsonify).
|
||||
|
||||
You can also pass in a custom comparison function.
|
||||
|
||||
[](https://travis-ci.org/epoberezkin/fast-json-stable-stringify)
|
||||
[](https://coveralls.io/github/epoberezkin/fast-json-stable-stringify?branch=master)
|
||||
|
||||
# example
|
||||
|
||||
``` js
|
||||
var stringify = require('fast-json-stable-stringify');
|
||||
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
|
||||
console.log(stringify(obj));
|
||||
```
|
||||
|
||||
output:
|
||||
|
||||
```
|
||||
{"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8}
|
||||
```
|
||||
|
||||
|
||||
# methods
|
||||
|
||||
``` js
|
||||
var stringify = require('fast-json-stable-stringify')
|
||||
```
|
||||
|
||||
## var str = stringify(obj, opts)
|
||||
|
||||
Return a deterministic stringified string `str` from the object `obj`.
|
||||
|
||||
|
||||
## options
|
||||
|
||||
### cmp
|
||||
|
||||
If `opts` is given, you can supply an `opts.cmp` to have a custom comparison
|
||||
function for object keys. Your function `opts.cmp` is called with these
|
||||
parameters:
|
||||
|
||||
``` js
|
||||
opts.cmp({ key: akey, value: avalue }, { key: bkey, value: bvalue })
|
||||
```
|
||||
|
||||
For example, to sort on the object key names in reverse order you could write:
|
||||
|
||||
``` js
|
||||
var stringify = require('fast-json-stable-stringify');
|
||||
|
||||
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
|
||||
var s = stringify(obj, function (a, b) {
|
||||
return a.key < b.key ? 1 : -1;
|
||||
});
|
||||
console.log(s);
|
||||
```
|
||||
|
||||
which results in the output string:
|
||||
|
||||
```
|
||||
{"c":8,"b":[{"z":6,"y":5,"x":4},7],"a":3}
|
||||
```
|
||||
|
||||
Or if you wanted to sort on the object values in reverse order, you could write:
|
||||
|
||||
```
|
||||
var stringify = require('fast-json-stable-stringify');
|
||||
|
||||
var obj = { d: 6, c: 5, b: [{z:3,y:2,x:1},9], a: 10 };
|
||||
var s = stringify(obj, function (a, b) {
|
||||
return a.value < b.value ? 1 : -1;
|
||||
});
|
||||
console.log(s);
|
||||
```
|
||||
|
||||
which outputs:
|
||||
|
||||
```
|
||||
{"d":6,"c":5,"b":[{"z":3,"y":2,"x":1},9],"a":10}
|
||||
```
|
||||
|
||||
### cycles
|
||||
|
||||
Pass `true` in `opts.cycles` to stringify circular property as `__cycle__` - the result will not be a valid JSON string in this case.
|
||||
|
||||
TypeError will be thrown in case of circular object without this option.
|
||||
|
||||
|
||||
# install
|
||||
|
||||
With [npm](https://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm install fast-json-stable-stringify
|
||||
```
|
||||
|
||||
|
||||
# benchmark
|
||||
|
||||
To run benchmark (requires Node.js 6+):
|
||||
```
|
||||
node benchmark
|
||||
```
|
||||
|
||||
Results:
|
||||
```
|
||||
fast-json-stable-stringify x 17,189 ops/sec ±1.43% (83 runs sampled)
|
||||
json-stable-stringify x 13,634 ops/sec ±1.39% (85 runs sampled)
|
||||
fast-stable-stringify x 20,212 ops/sec ±1.20% (84 runs sampled)
|
||||
faster-stable-stringify x 15,549 ops/sec ±1.12% (84 runs sampled)
|
||||
The fastest is fast-stable-stringify
|
||||
```
|
||||
|
||||
|
||||
## Enterprise support
|
||||
|
||||
fast-json-stable-stringify package is a part of [Tidelift enterprise subscription](https://tidelift.com/subscription/pkg/npm-fast-json-stable-stringify?utm_source=npm-fast-json-stable-stringify&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) - it provides a centralised commercial support to open-source software users, in addition to the support provided by software maintainers.
|
||||
|
||||
|
||||
## Security contact
|
||||
|
||||
To report a security vulnerability, please use the
|
||||
[Tidelift security contact](https://tidelift.com/security).
|
||||
Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerability via GitHub issues.
|
||||
|
||||
|
||||
# license
|
||||
|
||||
[MIT](https://github.com/epoberezkin/fast-json-stable-stringify/blob/master/LICENSE)
|
||||
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* A minimal ruleset that sets only the required parser and plugin options needed to run typescript-eslint.
|
||||
* We don't recommend using this directly; instead, extend from an earlier recommended rule.
|
||||
* @see {@link https://typescript-eslint.io/users/configs#base}
|
||||
*/
|
||||
exports.default = (plugin, parser) => ({
|
||||
name: 'typescript-eslint/base',
|
||||
languageOptions: {
|
||||
parser,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': plugin,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* @fileoverview An object that caches and applies source code fixes.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const debug = require("debug")("eslint:source-code-fixer");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const BOM = "\uFEFF";
|
||||
|
||||
/**
|
||||
* Compares items in a messages array by range.
|
||||
* @param {Message} a The first message.
|
||||
* @param {Message} b The second message.
|
||||
* @returns {number} -1 if a comes before b, 1 if a comes after b, 0 if equal.
|
||||
* @private
|
||||
*/
|
||||
function compareMessagesByFixRange(a, b) {
|
||||
return a.fix.range[0] - b.fix.range[0] || a.fix.range[1] - b.fix.range[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares items in a messages array by line and column.
|
||||
* @param {Message} a The first message.
|
||||
* @param {Message} b The second message.
|
||||
* @returns {number} -1 if a comes before b, 1 if a comes after b, 0 if equal.
|
||||
* @private
|
||||
*/
|
||||
function compareMessagesByLocation(a, b) {
|
||||
return a.line - b.line || a.column - b.column;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Utility for apply fixes to source code.
|
||||
* @constructor
|
||||
*/
|
||||
function SourceCodeFixer() {
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the fixes specified by the messages to the given text. Tries to be
|
||||
* smart about the fixes and won't apply fixes over the same area in the text.
|
||||
* @param {string} sourceText The text to apply the changes to.
|
||||
* @param {Message[]} messages The array of messages reported by ESLint.
|
||||
* @param {boolean|Function} [shouldFix=true] Determines whether each message should be fixed
|
||||
* @returns {Object} An object containing the fixed text and any unfixed messages.
|
||||
*/
|
||||
SourceCodeFixer.applyFixes = function (sourceText, messages, shouldFix) {
|
||||
debug("Applying fixes");
|
||||
|
||||
if (shouldFix === false) {
|
||||
debug("shouldFix parameter was false, not attempting fixes");
|
||||
return {
|
||||
fixed: false,
|
||||
messages,
|
||||
output: sourceText,
|
||||
};
|
||||
}
|
||||
|
||||
// clone the array
|
||||
const remainingMessages = [],
|
||||
fixes = [],
|
||||
bom = sourceText.startsWith(BOM) ? BOM : "",
|
||||
text = bom ? sourceText.slice(1) : sourceText;
|
||||
let lastPos = Number.NEGATIVE_INFINITY,
|
||||
output = bom;
|
||||
|
||||
/**
|
||||
* Try to use the 'fix' from a problem.
|
||||
* @param {Message} problem The message object to apply fixes from
|
||||
* @returns {boolean} Whether fix was successfully applied
|
||||
*/
|
||||
function attemptFix(problem) {
|
||||
const fix = problem.fix;
|
||||
const start = fix.range[0];
|
||||
const end = fix.range[1];
|
||||
|
||||
// Remain it as a problem if it's overlapped or it's a negative range
|
||||
if (lastPos >= start || start > end) {
|
||||
remainingMessages.push(problem);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove BOM.
|
||||
if (
|
||||
(start < 0 && end >= 0) ||
|
||||
(start === 0 && fix.text.startsWith(BOM))
|
||||
) {
|
||||
output = "";
|
||||
}
|
||||
|
||||
// Make output to this fix.
|
||||
output += text.slice(Math.max(0, lastPos), Math.max(0, start));
|
||||
output += fix.text;
|
||||
lastPos = end;
|
||||
return true;
|
||||
}
|
||||
|
||||
messages.forEach(problem => {
|
||||
if (Object.hasOwn(problem, "fix") && problem.fix) {
|
||||
fixes.push(problem);
|
||||
} else {
|
||||
remainingMessages.push(problem);
|
||||
}
|
||||
});
|
||||
|
||||
if (fixes.length) {
|
||||
debug("Found fixes to apply");
|
||||
let fixesWereApplied = false;
|
||||
|
||||
for (const problem of fixes.sort(compareMessagesByFixRange)) {
|
||||
if (typeof shouldFix !== "function" || shouldFix(problem)) {
|
||||
attemptFix(problem);
|
||||
|
||||
/*
|
||||
* The only time attemptFix will fail is if a previous fix was
|
||||
* applied which conflicts with it. So we can mark this as true.
|
||||
*/
|
||||
fixesWereApplied = true;
|
||||
} else {
|
||||
remainingMessages.push(problem);
|
||||
}
|
||||
}
|
||||
output += text.slice(Math.max(0, lastPos));
|
||||
|
||||
return {
|
||||
fixed: fixesWereApplied,
|
||||
messages: remainingMessages.sort(compareMessagesByLocation),
|
||||
output,
|
||||
};
|
||||
}
|
||||
|
||||
debug("No fixes to apply");
|
||||
return {
|
||||
fixed: false,
|
||||
messages,
|
||||
output: bom + text,
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = SourceCodeFixer;
|
||||
@@ -0,0 +1,8 @@
|
||||
function _defineAccessor(e, r, n, t) {
|
||||
var c = {
|
||||
configurable: !0,
|
||||
enumerable: !0
|
||||
};
|
||||
return c[e] = t, Object.defineProperty(r, n, c);
|
||||
}
|
||||
module.exports = _defineAccessor, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,196 @@
|
||||
"use strict";
|
||||
|
||||
const conversions = require("webidl-conversions");
|
||||
const utils = require("./utils.js");
|
||||
const Impl = require(".//URL-impl.js");
|
||||
|
||||
const impl = utils.implSymbol;
|
||||
|
||||
function URL(url) {
|
||||
if (!this || this[impl] || !(this instanceof URL)) {
|
||||
throw new TypeError("Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function.");
|
||||
}
|
||||
if (arguments.length < 1) {
|
||||
throw new TypeError("Failed to construct 'URL': 1 argument required, but only " + arguments.length + " present.");
|
||||
}
|
||||
const args = [];
|
||||
for (let i = 0; i < arguments.length && i < 2; ++i) {
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
args[0] = conversions["USVString"](args[0]);
|
||||
if (args[1] !== undefined) {
|
||||
args[1] = conversions["USVString"](args[1]);
|
||||
}
|
||||
|
||||
module.exports.setup(this, args);
|
||||
}
|
||||
|
||||
URL.prototype.toJSON = function toJSON() {
|
||||
if (!this || !module.exports.is(this)) {
|
||||
throw new TypeError("Illegal invocation");
|
||||
}
|
||||
const args = [];
|
||||
for (let i = 0; i < arguments.length && i < 0; ++i) {
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
return this[impl].toJSON.apply(this[impl], args);
|
||||
};
|
||||
Object.defineProperty(URL.prototype, "href", {
|
||||
get() {
|
||||
return this[impl].href;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].href = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
URL.prototype.toString = function () {
|
||||
if (!this || !module.exports.is(this)) {
|
||||
throw new TypeError("Illegal invocation");
|
||||
}
|
||||
return this.href;
|
||||
};
|
||||
|
||||
Object.defineProperty(URL.prototype, "origin", {
|
||||
get() {
|
||||
return this[impl].origin;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "protocol", {
|
||||
get() {
|
||||
return this[impl].protocol;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].protocol = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "username", {
|
||||
get() {
|
||||
return this[impl].username;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].username = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "password", {
|
||||
get() {
|
||||
return this[impl].password;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].password = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "host", {
|
||||
get() {
|
||||
return this[impl].host;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].host = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "hostname", {
|
||||
get() {
|
||||
return this[impl].hostname;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].hostname = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "port", {
|
||||
get() {
|
||||
return this[impl].port;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].port = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "pathname", {
|
||||
get() {
|
||||
return this[impl].pathname;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].pathname = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "search", {
|
||||
get() {
|
||||
return this[impl].search;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].search = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(URL.prototype, "hash", {
|
||||
get() {
|
||||
return this[impl].hash;
|
||||
},
|
||||
set(V) {
|
||||
V = conversions["USVString"](V);
|
||||
this[impl].hash = V;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
|
||||
module.exports = {
|
||||
is(obj) {
|
||||
return !!obj && obj[impl] instanceof Impl.implementation;
|
||||
},
|
||||
create(constructorArgs, privateData) {
|
||||
let obj = Object.create(URL.prototype);
|
||||
this.setup(obj, constructorArgs, privateData);
|
||||
return obj;
|
||||
},
|
||||
setup(obj, constructorArgs, privateData) {
|
||||
if (!privateData) privateData = {};
|
||||
privateData.wrapper = obj;
|
||||
|
||||
obj[impl] = new Impl.implementation(constructorArgs, privateData);
|
||||
obj[impl][utils.wrapperSymbol] = obj;
|
||||
},
|
||||
interface: URL,
|
||||
expose: {
|
||||
Window: { URL: URL },
|
||||
Worker: { URL: URL }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { expect } from 'tstyche'
|
||||
import { createDeprecation, createWarning, spyWarning, WarningCallData, WarningSpyData } from '..'
|
||||
|
||||
const WarnInstance = createWarning({
|
||||
name: 'TypeScriptWarning',
|
||||
code: 'CODE',
|
||||
message: 'message'
|
||||
})
|
||||
|
||||
expect(WarnInstance.code).type.toBe<string>()
|
||||
expect(WarnInstance.message).type.toBe<string>()
|
||||
expect(WarnInstance.name).type.toBe<string>()
|
||||
expect(WarnInstance.emitted).type.toBe<boolean>()
|
||||
expect(WarnInstance.unlimited).type.toBe<boolean>()
|
||||
|
||||
expect(WarnInstance()).type.toBe<boolean>()
|
||||
expect(WarnInstance('foo')).type.toBe<boolean>()
|
||||
expect(WarnInstance('foo', 'bar')).type.toBe<boolean>()
|
||||
|
||||
const buildWarnUnlimited = createWarning({
|
||||
name: 'TypeScriptWarning',
|
||||
code: 'CODE',
|
||||
message: 'message',
|
||||
unlimited: true
|
||||
})
|
||||
|
||||
expect(buildWarnUnlimited.unlimited).type.toBe<boolean>()
|
||||
|
||||
const DeprecationInstance = createDeprecation({
|
||||
code: 'CODE',
|
||||
message: 'message'
|
||||
})
|
||||
|
||||
expect(DeprecationInstance.code).type.toBe<string>()
|
||||
|
||||
expect(DeprecationInstance()).type.toBe<boolean>()
|
||||
expect(DeprecationInstance('foo')).type.toBe<boolean>()
|
||||
expect(DeprecationInstance('foo', 'bar')).type.toBe<boolean>()
|
||||
|
||||
const spyData = spyWarning(WarnInstance)
|
||||
expect(spyData).type.toBe<WarningSpyData>()
|
||||
expect(spyData.calls).type.toBe<WarningCallData[]>()
|
||||
expect(spyData.callCount).type.toBe<(() => number)>()
|
||||
expect(spyData.callCount()).type.toBe<number>()
|
||||
expect(spyData.reset).type.toBe<(() => void)>()
|
||||
expect(spyData.reset()).type.toBe<void>()
|
||||
expect(spyData.restore).type.toBe<(() => void)>()
|
||||
expect(spyData.restore()).type.toBe<void>()
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"name": "ignore",
|
||||
"version": "5.3.2",
|
||||
"description": "Ignore is a manager and filter for .gitignore rules, the one used by eslint, gitbook and many others.",
|
||||
"files": [
|
||||
"legacy.js",
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"LICENSE-MIT"
|
||||
],
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
"build": "babel -o legacy.js index.js",
|
||||
"test:lint": "eslint .",
|
||||
"test:tsc": "tsc ./test/ts/simple.ts --lib ES6",
|
||||
"test:ts": "node ./test/ts/simple.js",
|
||||
"tap": "tap --reporter classic",
|
||||
"test:git": "npm run tap test/git-check-ignore.js",
|
||||
"test:ignore": "npm run tap test/ignore.js",
|
||||
"test:ignore:only": "IGNORE_ONLY_IGNORES=1 npm run tap test/ignore.js",
|
||||
"test:others": "npm run tap test/others.js",
|
||||
"test:cases": "npm run tap test/*.js -- --coverage",
|
||||
"test:no-coverage": "npm run tap test/*.js -- --no-check-coverage",
|
||||
"test:only": "npm run test:lint && npm run test:tsc && npm run test:ts && npm run test:cases",
|
||||
"test": "npm run test:only",
|
||||
"test:win32": "IGNORE_TEST_WIN32=1 npm run test",
|
||||
"report": "tap --coverage-report=html",
|
||||
"posttest": "npm run report && codecov"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:kaelzhang/node-ignore.git"
|
||||
},
|
||||
"keywords": [
|
||||
"ignore",
|
||||
".gitignore",
|
||||
"gitignore",
|
||||
"npmignore",
|
||||
"rules",
|
||||
"manager",
|
||||
"filter",
|
||||
"regexp",
|
||||
"regex",
|
||||
"fnmatch",
|
||||
"glob",
|
||||
"asterisks",
|
||||
"regular-expression"
|
||||
],
|
||||
"author": "kael",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/kaelzhang/node-ignore/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.22.9",
|
||||
"@babel/core": "^7.22.9",
|
||||
"@babel/preset-env": "^7.22.9",
|
||||
"codecov": "^3.8.2",
|
||||
"debug": "^4.3.4",
|
||||
"eslint": "^8.46.0",
|
||||
"eslint-config-ostai": "^3.0.0",
|
||||
"eslint-plugin-import": "^2.28.0",
|
||||
"mkdirp": "^3.0.1",
|
||||
"pre-suf": "^1.1.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"spawn-sync": "^2.0.0",
|
||||
"tap": "^16.3.9",
|
||||
"tmp": "0.2.3",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
import { a as RolldownLog } from "./logging-xuHO4mAy.mjs";
|
||||
import { F as MinifyOptions$1, G as TsconfigCache$1, I as MinifyResult$1, R as ParseResult$1, U as SourceMap, a as BindingEnhancedTransformOptions, o as BindingEnhancedTransformResult, y as BindingTsconfigResult, z as ParserOptions$1 } from "./binding-CVtkJvyl.mjs";
|
||||
//#region src/utils/resolve-tsconfig.d.ts
|
||||
/**
|
||||
* Cache for tsconfig resolution to avoid redundant file system operations.
|
||||
*
|
||||
* The cache stores resolved tsconfig configurations keyed by their file paths.
|
||||
* When transforming multiple files in the same project, tsconfig lookups are
|
||||
* deduplicated, improving performance.
|
||||
*
|
||||
* @category Utilities
|
||||
* @experimental
|
||||
*/
|
||||
declare class TsconfigCache extends TsconfigCache$1 {
|
||||
constructor();
|
||||
}
|
||||
/** @hidden This is only expected to be used by Vite */
|
||||
declare function resolveTsconfig(filename: string, cache?: TsconfigCache | null): BindingTsconfigResult | null;
|
||||
//#endregion
|
||||
//#region src/utils/parse.d.ts
|
||||
/**
|
||||
* Result of parsing a code
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
interface ParseResult extends ParseResult$1 {}
|
||||
/**
|
||||
* Options for parsing a code
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
interface ParserOptions extends ParserOptions$1 {}
|
||||
/**
|
||||
* Parse JS/TS source asynchronously on a separate thread.
|
||||
*
|
||||
* Note that not all of the workload can happen on a separate thread.
|
||||
* Parsing on Rust side does happen in a separate thread, but deserialization of the AST to JS objects
|
||||
* has to happen on current thread. This synchronous deserialization work typically outweighs
|
||||
* the asynchronous parsing by a factor of between 3 and 20.
|
||||
*
|
||||
* i.e. the majority of the workload cannot be parallelized by using this method.
|
||||
*
|
||||
* Generally {@linkcode parseSync} is preferable to use as it does not have the overhead of spawning a thread.
|
||||
* If you need to parallelize parsing multiple files, it is recommended to use worker threads.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
declare function parse(filename: string, sourceText: string, options?: ParserOptions | null): Promise<ParseResult>;
|
||||
/**
|
||||
* Parse JS/TS source synchronously on current thread.
|
||||
*
|
||||
* This is generally preferable over {@linkcode parse} (async) as it does not have the overhead
|
||||
* of spawning a thread, and the majority of the workload cannot be parallelized anyway
|
||||
* (see {@linkcode parse} documentation for details).
|
||||
*
|
||||
* If you need to parallelize parsing multiple files, it is recommended to use worker threads
|
||||
* with {@linkcode parseSync} rather than using {@linkcode parse}.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
declare function parseSync(filename: string, sourceText: string, options?: ParserOptions | null): ParseResult;
|
||||
//#endregion
|
||||
//#region src/utils/minify.d.ts
|
||||
/**
|
||||
* Options for minification.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
interface MinifyOptions extends MinifyOptions$1 {
|
||||
inputMap?: SourceMap;
|
||||
}
|
||||
/**
|
||||
* The result of minification.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
interface MinifyResult extends MinifyResult$1 {}
|
||||
/**
|
||||
* Minify asynchronously.
|
||||
*
|
||||
* Note: This function can be slower than {@linkcode minifySync} due to the overhead of spawning a thread.
|
||||
*
|
||||
* @category Utilities
|
||||
* @experimental
|
||||
*/
|
||||
declare function minify(filename: string, sourceText: string, options?: MinifyOptions | null): Promise<MinifyResult>;
|
||||
/**
|
||||
* Minify synchronously.
|
||||
*
|
||||
* @category Utilities
|
||||
* @experimental
|
||||
*/
|
||||
declare function minifySync(filename: string, sourceText: string, options?: MinifyOptions | null): MinifyResult;
|
||||
//#endregion
|
||||
//#region src/utils/transform.d.ts
|
||||
/**
|
||||
* Options for transforming a code.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
interface TransformOptions extends BindingEnhancedTransformOptions {}
|
||||
/**
|
||||
* Result of transforming a code.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
type TransformResult = Omit<BindingEnhancedTransformResult, "errors" | "warnings"> & {
|
||||
errors: Error[];
|
||||
warnings: RolldownLog[];
|
||||
};
|
||||
/**
|
||||
* Transpile a JavaScript or TypeScript into a target ECMAScript version, asynchronously.
|
||||
*
|
||||
* Note: This function can be slower than `transformSync` due to the overhead of spawning a thread.
|
||||
*
|
||||
* @param filename The name of the file being transformed. If this is a
|
||||
* relative path, consider setting the {@linkcode TransformOptions#cwd} option.
|
||||
* @param sourceText The source code to transform.
|
||||
* @param options The transform options including tsconfig and inputMap. See {@linkcode TransformOptions} for more information.
|
||||
* @param cache Optional tsconfig cache for reusing resolved tsconfig across multiple transforms.
|
||||
* Only used when `options.tsconfig` is `true`.
|
||||
*
|
||||
* @returns a promise that resolves to an object containing the transformed code,
|
||||
* source maps, and any errors that occurred during parsing or transformation.
|
||||
*
|
||||
* @category Utilities
|
||||
* @experimental
|
||||
*/
|
||||
declare function transform(filename: string, sourceText: string, options?: TransformOptions | null, cache?: TsconfigCache | null): Promise<TransformResult>;
|
||||
/**
|
||||
* Transpile a JavaScript or TypeScript into a target ECMAScript version.
|
||||
*
|
||||
* @param filename The name of the file being transformed. If this is a
|
||||
* relative path, consider setting the {@linkcode TransformOptions#cwd} option.
|
||||
* @param sourceText The source code to transform.
|
||||
* @param options The transform options including tsconfig and inputMap. See {@linkcode TransformOptions} for more information.
|
||||
* @param cache Optional tsconfig cache for reusing resolved tsconfig across multiple transforms.
|
||||
* Only used when `options.tsconfig` is `true`.
|
||||
*
|
||||
* @returns an object containing the transformed code, source maps, and any errors
|
||||
* that occurred during parsing or transformation.
|
||||
*
|
||||
* @category Utilities
|
||||
* @experimental
|
||||
*/
|
||||
declare function transformSync(filename: string, sourceText: string, options?: TransformOptions | null, cache?: TsconfigCache | null): TransformResult;
|
||||
//#endregion
|
||||
export { MinifyOptions as a, minifySync as c, parse as d, parseSync as f, transformSync as i, ParseResult as l, resolveTsconfig as m, TransformResult as n, MinifyResult as o, TsconfigCache as p, transform as r, minify as s, TransformOptions as t, ParserOptions as u };
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.esnext_string = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.esnext_string = {
|
||||
libs: [],
|
||||
variables: [['String', base_config_1.TYPE]],
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
function _get_prototype_of(o) {
|
||||
_get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
|
||||
return o.__proto__ || Object.getPrototypeOf(o);
|
||||
};
|
||||
|
||||
return _get_prototype_of(o);
|
||||
}
|
||||
export { _get_prototype_of as _ };
|
||||
@@ -0,0 +1,12 @@
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { TSESTree } from '@typescript-eslint/types';
|
||||
import type { ScopeManager } from '../ScopeManager';
|
||||
import type { Scope } from './Scope';
|
||||
import { ScopeBase } from './ScopeBase';
|
||||
import { ScopeType } from './ScopeType';
|
||||
export declare class TSModuleScope extends ScopeBase<ScopeType.tsModule, TSESTree.TSModuleDeclaration, Scope> {
|
||||
constructor(scopeManager: ScopeManager, upperScope: TSModuleScope['upper'], block: TSModuleScope['block']);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
this is hello world
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "whatwg-url",
|
||||
"version": "5.0.0",
|
||||
"description": "An implementation of the WHATWG URL Standard's URL API and parsing machinery",
|
||||
"main": "lib/public-api.js",
|
||||
"files": [
|
||||
"lib/"
|
||||
],
|
||||
"author": "Sebastian Mayr <github@smayr.name>",
|
||||
"license": "MIT",
|
||||
"repository": "jsdom/whatwg-url",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^2.6.0",
|
||||
"istanbul": "~0.4.3",
|
||||
"mocha": "^2.2.4",
|
||||
"recast": "~0.10.29",
|
||||
"request": "^2.55.0",
|
||||
"webidl2js": "^3.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node scripts/transform.js && node scripts/convert-idl.js",
|
||||
"coverage": "istanbul cover node_modules/mocha/bin/_mocha",
|
||||
"lint": "eslint .",
|
||||
"prepublish": "npm run build",
|
||||
"pretest": "node scripts/get-latest-platform-tests.js && npm run build",
|
||||
"test": "mocha"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
'use strict'
|
||||
|
||||
process.env.TZ = 'UTC'
|
||||
|
||||
const path = require('node:path')
|
||||
const { spawn } = require('node:child_process')
|
||||
const { describe, after, test } = require('node:test')
|
||||
const match = require('@jsumners/assert-match')
|
||||
const fs = require('node:fs')
|
||||
const { rimraf } = require('rimraf')
|
||||
const { once } = require('./helper')
|
||||
|
||||
const bin = require.resolve('../bin')
|
||||
const logLine = '{"level":30,"time":1522431328992,"msg":"hello world","pid":42,"hostname":"foo"}\n'
|
||||
|
||||
describe('cli', () => {
|
||||
const tmpDir = path.join(__dirname, '.tmp_' + Date.now())
|
||||
fs.mkdirSync(tmpDir)
|
||||
|
||||
after(() => rimraf(tmpDir))
|
||||
|
||||
test('loads and applies default config file: pino-pretty.config.js', async (t) => {
|
||||
t.plan(1)
|
||||
// Set translateTime: true on run configuration
|
||||
const configFile = path.join(tmpDir, 'pino-pretty.config.js')
|
||||
fs.writeFileSync(configFile, 'module.exports = { translateTime: true }')
|
||||
const env = { TERM: 'dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin], { env, cwd: tmpDir })
|
||||
// Validate that the time has been translated
|
||||
child.on('error', t.assert.fail)
|
||||
const endPromise = once(child.stdout, 'data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), '[17:35:28.992] INFO (42): hello world\n')
|
||||
})
|
||||
child.stdin.write(logLine)
|
||||
await endPromise
|
||||
t.after(() => {
|
||||
fs.unlinkSync(configFile)
|
||||
child.kill()
|
||||
})
|
||||
})
|
||||
|
||||
test('loads and applies default config file: pino-pretty.config.cjs', async (t) => {
|
||||
t.plan(1)
|
||||
// Set translateTime: true on run configuration
|
||||
const configFile = path.join(tmpDir, 'pino-pretty.config.cjs')
|
||||
fs.writeFileSync(configFile, 'module.exports = { translateTime: true }')
|
||||
// Tell the loader to expect ESM modules
|
||||
const packageJsonFile = path.join(tmpDir, 'package.json')
|
||||
fs.writeFileSync(packageJsonFile, JSON.stringify({ type: 'module' }, null, 4))
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin], { env, cwd: tmpDir })
|
||||
// Validate that the time has been translated
|
||||
child.on('error', t.assert.fail)
|
||||
const endPromise = once(child.stdout, 'data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), '[17:35:28.992] INFO (42): hello world\n')
|
||||
})
|
||||
child.stdin.write(logLine)
|
||||
await endPromise
|
||||
t.after(() => {
|
||||
fs.unlinkSync(configFile)
|
||||
fs.unlinkSync(packageJsonFile)
|
||||
child.kill()
|
||||
})
|
||||
})
|
||||
|
||||
test('loads and applies default config file: .pino-prettyrc', async (t) => {
|
||||
t.plan(1)
|
||||
// Set translateTime: true on run configuration
|
||||
const configFile = path.join(tmpDir, '.pino-prettyrc')
|
||||
fs.writeFileSync(configFile, JSON.stringify({ translateTime: true }, null, 4))
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin], { env, cwd: tmpDir })
|
||||
// Validate that the time has been translated
|
||||
child.on('error', t.assert.fail)
|
||||
const endPromise = once(child.stdout, 'data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), '[17:35:28.992] INFO (42): hello world\n')
|
||||
})
|
||||
child.stdin.write(logLine)
|
||||
await endPromise
|
||||
t.after(() => {
|
||||
fs.unlinkSync(configFile)
|
||||
child.kill()
|
||||
})
|
||||
})
|
||||
|
||||
test('loads and applies default config file: .pino-prettyrc.json', async (t) => {
|
||||
t.plan(1)
|
||||
// Set translateTime: true on run configuration
|
||||
const configFile = path.join(tmpDir, '.pino-prettyrc.json')
|
||||
fs.writeFileSync(configFile, JSON.stringify({ translateTime: true }, null, 4))
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin], { env, cwd: tmpDir })
|
||||
// Validate that the time has been translated
|
||||
child.on('error', t.assert.fail)
|
||||
const endPromise = once(child.stdout, 'data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), '[17:35:28.992] INFO (42): hello world\n')
|
||||
})
|
||||
child.stdin.write(logLine)
|
||||
await endPromise
|
||||
t.after(() => {
|
||||
fs.unlinkSync(configFile)
|
||||
child.kill()
|
||||
})
|
||||
})
|
||||
|
||||
test('loads and applies custom config file: pino-pretty.config.test.json', async (t) => {
|
||||
t.plan(1)
|
||||
// Set translateTime: true on run configuration
|
||||
const configFile = path.join(tmpDir, 'pino-pretty.config.test.json')
|
||||
fs.writeFileSync(configFile, JSON.stringify({ translateTime: true }, null, 4))
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin, '--config', configFile], { env, cwd: tmpDir })
|
||||
// Validate that the time has been translated
|
||||
child.on('error', t.assert.fail)
|
||||
const endPromise = once(child.stdout, 'data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), '[17:35:28.992] INFO (42): hello world\n')
|
||||
})
|
||||
child.stdin.write(logLine)
|
||||
await endPromise
|
||||
t.after(() => child.kill())
|
||||
})
|
||||
|
||||
test('loads and applies custom config file: pino-pretty.config.test.js', async (t) => {
|
||||
t.plan(1)
|
||||
// Set translateTime: true on run configuration
|
||||
const configFile = path.join(tmpDir, 'pino-pretty.config.test.js')
|
||||
fs.writeFileSync(configFile, 'module.exports = { translateTime: true }')
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin, '--config', configFile], { env, cwd: tmpDir })
|
||||
// Validate that the time has been translated
|
||||
child.on('error', t.assert.fail)
|
||||
const endPromise = once(child.stdout, 'data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), '[17:35:28.992] INFO (42): hello world\n')
|
||||
})
|
||||
child.stdin.write(logLine)
|
||||
await endPromise
|
||||
t.after(() => child.kill())
|
||||
})
|
||||
|
||||
for (const optionName of ['--messageKey', '-m']) {
|
||||
test(`cli options override config options via ${optionName}`, async (t) => {
|
||||
t.plan(1)
|
||||
// Set translateTime: true on run configuration
|
||||
const configFile = path.join(tmpDir, 'pino-pretty.config.js')
|
||||
fs.writeFileSync(configFile, `
|
||||
module.exports = {
|
||||
translateTime: true,
|
||||
messageKey: 'custom_msg'
|
||||
}
|
||||
`.trim())
|
||||
// Set messageKey: 'new_msg' using command line option
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin, optionName, 'new_msg'], { env, cwd: tmpDir })
|
||||
// Validate that the time has been translated and correct message key has been used
|
||||
child.on('error', t.assert.fail)
|
||||
const endPromise = once(child.stdout, 'data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), '[17:35:28.992] INFO (42): hello world\n')
|
||||
})
|
||||
child.stdin.write(logLine.replace(/"msg"/, '"new_msg"'))
|
||||
await endPromise
|
||||
t.after(() => {
|
||||
fs.unlinkSync(configFile)
|
||||
child.kill()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
test('cli options with defaults can be overridden by config', async (t) => {
|
||||
t.plan(1)
|
||||
// Set errorProps: '*' on run configuration
|
||||
const configFile = path.join(tmpDir, 'pino-pretty.config.js')
|
||||
fs.writeFileSync(configFile, `
|
||||
module.exports = {
|
||||
errorProps: '*'
|
||||
}
|
||||
`.trim())
|
||||
// Set messageKey: 'new_msg' using command line option
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin], { env, cwd: tmpDir })
|
||||
// Validate that the time has been translated and correct message key has been used
|
||||
child.on('error', t.assert.fail)
|
||||
const endPromise = once(child.stdout, 'data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), '[21:31:36.006] FATAL: There was an error starting the process.\n QueryError: Error during sql query: syntax error at or near SELECTT\n at /home/me/projects/example/sql.js\n at /home/me/projects/example/index.js\n querySql: SELECTT * FROM "test" WHERE id = $1;\n queryArgs: 12\n')
|
||||
})
|
||||
child.stdin.write('{"level":60,"time":1594416696006,"msg":"There was an error starting the process.","type":"Error","stack":"QueryError: Error during sql query: syntax error at or near SELECTT\\n at /home/me/projects/example/sql.js\\n at /home/me/projects/example/index.js","querySql":"SELECTT * FROM \\"test\\" WHERE id = $1;","queryArgs":[12]}\n')
|
||||
await endPromise
|
||||
t.after(() => {
|
||||
fs.unlinkSync(configFile)
|
||||
child.kill()
|
||||
})
|
||||
})
|
||||
|
||||
test('throws on missing config file', async (t) => {
|
||||
t.plan(2)
|
||||
const args = [bin, '--config', 'pino-pretty.config.missing.json']
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], args, { env, cwd: tmpDir })
|
||||
const endPromise1 = once(child, 'close', (code) => {
|
||||
t.assert.strictEqual(code, 1)
|
||||
})
|
||||
child.stdout.pipe(process.stdout)
|
||||
child.stderr.setEncoding('utf8')
|
||||
let data = ''
|
||||
child.stderr.on('data', (chunk) => {
|
||||
data += chunk
|
||||
})
|
||||
const endPromise2 = once(child, 'close', () => {
|
||||
match(
|
||||
data.toString(), 'Error: Failed to load runtime configuration file: pino-pretty.config.missing.json', t)
|
||||
})
|
||||
await Promise.all([endPromise1, endPromise2])
|
||||
t.after(() => child.kill())
|
||||
})
|
||||
|
||||
test('throws on invalid default config file', async (t) => {
|
||||
t.plan(2)
|
||||
const configFile = path.join(tmpDir, 'pino-pretty.config.js')
|
||||
fs.writeFileSync(configFile, 'module.exports = () => {}')
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin], { env, cwd: tmpDir })
|
||||
const endPromise1 = once(child, 'close', (code) => {
|
||||
t.assert.strictEqual(code, 1)
|
||||
})
|
||||
child.stdout.pipe(process.stdout)
|
||||
child.stderr.setEncoding('utf8')
|
||||
let data = ''
|
||||
child.stderr.on('data', (chunk) => {
|
||||
data += chunk
|
||||
})
|
||||
const endPromise2 = once(child, 'close', () => {
|
||||
match(data, 'Error: Invalid runtime configuration file: pino-pretty.config.js', t)
|
||||
})
|
||||
await Promise.all([endPromise1, endPromise2])
|
||||
t.after(() => child.kill())
|
||||
})
|
||||
|
||||
test('throws on invalid custom config file', async (t) => {
|
||||
t.plan(2)
|
||||
const configFile = path.join(tmpDir, 'pino-pretty.config.invalid.js')
|
||||
fs.writeFileSync(configFile, 'module.exports = () => {}')
|
||||
const args = [bin, '--config', path.relative(tmpDir, configFile)]
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], args, { env, cwd: tmpDir })
|
||||
const endPromise1 = once(child, 'close', (code) => {
|
||||
t.assert.strictEqual(code, 1)
|
||||
})
|
||||
child.stdout.pipe(process.stdout)
|
||||
child.stderr.setEncoding('utf8')
|
||||
let data = ''
|
||||
child.stderr.on('data', (chunk) => {
|
||||
data += chunk
|
||||
})
|
||||
const endPromise2 = once(child, 'close', () => {
|
||||
match(data, 'Error: Invalid runtime configuration file: pino-pretty.config.invalid.js', t)
|
||||
})
|
||||
await Promise.all([endPromise1, endPromise2])
|
||||
t.after(() => child.kill())
|
||||
})
|
||||
|
||||
test('test help', async (t) => {
|
||||
t.plan(1)
|
||||
const env = { TERM: ' dumb', TZ: 'UTC' }
|
||||
const child = spawn(process.argv[0], [bin, '--help'], { env })
|
||||
const file = fs.readFileSync('help/help.txt').toString()
|
||||
child.on('error', t.assert.fail)
|
||||
|
||||
await new Promise(resolve => {
|
||||
child.stdout.on('data', (data) => {
|
||||
t.assert.strictEqual(data.toString(), file)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
t.after(() => child.kill())
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC"}
|
||||
Reference in New Issue
Block a user