WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const { createWarning } = require('..')
|
||||
const { spyWarning } = require('..')
|
||||
|
||||
test('Spy ProcessWarning - unlimited: false', t => {
|
||||
const warning = createWarning({
|
||||
name: 'Warning',
|
||||
code: 'WRN',
|
||||
message: 'Hello %s'
|
||||
})
|
||||
const spyData = spyWarning(warning)
|
||||
|
||||
t.assert.strictEqual(warning.emitted, false)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
|
||||
warning('World')
|
||||
t.assert.strictEqual(warning.emitted, true)
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World'])
|
||||
t.assert.strictEqual(spyData.calls[0].result, true)
|
||||
t.assert.strictEqual(spyData.callCount(), 1)
|
||||
|
||||
warning('World')
|
||||
t.assert.strictEqual(warning.emitted, true)
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World'])
|
||||
t.assert.strictEqual(spyData.calls[0].result, true)
|
||||
t.assert.deepStrictEqual(spyData.calls[1].arguments, ['World'])
|
||||
t.assert.strictEqual(spyData.calls[1].result, false)
|
||||
t.assert.strictEqual(spyData.callCount(), 2)
|
||||
|
||||
spyData.reset()
|
||||
t.assert.strictEqual(warning.emitted, false)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
|
||||
warning('World')
|
||||
t.assert.strictEqual(warning.emitted, true)
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World'])
|
||||
t.assert.strictEqual(spyData.calls[0].result, true)
|
||||
t.assert.strictEqual(spyData.callCount(), 1)
|
||||
|
||||
spyData.restore()
|
||||
t.assert.strictEqual(warning.emitted, false)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
|
||||
warning('World')
|
||||
t.assert.strictEqual(warning.emitted, true)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
})
|
||||
|
||||
test('Spy ProcessWarning - unlimited: true', t => {
|
||||
const warning = createWarning({
|
||||
name: 'Warning',
|
||||
code: 'WRN',
|
||||
message: 'Hello %s',
|
||||
unlimited: true
|
||||
})
|
||||
const spyData = spyWarning(warning)
|
||||
|
||||
t.assert.strictEqual(warning.emitted, false)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
|
||||
warning('World')
|
||||
t.assert.strictEqual(warning.emitted, true)
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World'])
|
||||
t.assert.strictEqual(spyData.calls[0].result, true)
|
||||
t.assert.strictEqual(spyData.callCount(), 1)
|
||||
|
||||
warning('World')
|
||||
t.assert.strictEqual(warning.emitted, true)
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World'])
|
||||
t.assert.strictEqual(spyData.calls[0].result, true)
|
||||
t.assert.deepStrictEqual(spyData.calls[1].arguments, ['World'])
|
||||
t.assert.strictEqual(spyData.calls[1].result, true)
|
||||
t.assert.strictEqual(spyData.callCount(), 2)
|
||||
|
||||
spyData.reset()
|
||||
t.assert.strictEqual(warning.emitted, false)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
|
||||
warning('World')
|
||||
t.assert.strictEqual(warning.emitted, true)
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World'])
|
||||
t.assert.strictEqual(spyData.calls[0].result, true)
|
||||
t.assert.strictEqual(spyData.callCount(), 1)
|
||||
|
||||
spyData.restore()
|
||||
t.assert.strictEqual(warning.emitted, false)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
|
||||
warning('World')
|
||||
t.assert.strictEqual(warning.emitted, true)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
})
|
||||
|
||||
test('Spy ProcessWarning - calls[].arguments', t => {
|
||||
const warning = createWarning({
|
||||
name: 'Warning',
|
||||
code: 'WRN',
|
||||
message: 'Hello %s'
|
||||
})
|
||||
const spyData = spyWarning(warning)
|
||||
|
||||
warning(undefined)
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, [])
|
||||
spyData.reset()
|
||||
|
||||
warning()
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, [])
|
||||
spyData.reset()
|
||||
|
||||
warning('World')
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World'])
|
||||
spyData.reset()
|
||||
|
||||
warning('World', 'Hello')
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World', 'Hello'])
|
||||
spyData.reset()
|
||||
|
||||
warning(undefined, 'Hello')
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, [undefined, 'Hello'])
|
||||
spyData.reset()
|
||||
|
||||
warning('World', 'Hello', 'World')
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World', 'Hello', 'World'])
|
||||
spyData.reset()
|
||||
|
||||
warning('World', undefined, 'World')
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['World', undefined, 'World'])
|
||||
spyData.reset()
|
||||
|
||||
warning(undefined, 'Hello', 'World')
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, [undefined, 'Hello', 'World'])
|
||||
spyData.reset()
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "quick-format-unescaped",
|
||||
"version": "4.0.4",
|
||||
"description": "Solves a problem with util.format",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "nyc -- node test",
|
||||
"test:html": "nyc --reporter=html -- node test"
|
||||
},
|
||||
"author": "David Mark Clements",
|
||||
"devDependencies": {
|
||||
"fastbench": "^1.0.1",
|
||||
"nyc": "^15.0.0"
|
||||
},
|
||||
"dependencies": {},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/davidmarkclements/quick-format.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/davidmarkclements/quick-format/issues"
|
||||
},
|
||||
"homepage": "https://github.com/davidmarkclements/quick-format#readme"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
global.process = { __proto__: process, pid: 123456 }
|
||||
Date.now = function () { return 1459875739796 }
|
||||
require('node:os').hostname = function () { return 'abcdefghijklmnopqr' }
|
||||
const pino = require(require.resolve('./../../'))
|
||||
const asyncLogger = pino(pino.destination({ sync: false })).child({ hello: 'world' })
|
||||
asyncLogger.info('h')
|
||||
@@ -0,0 +1,227 @@
|
||||
'use strict'
|
||||
|
||||
process.env.TZ = 'UTC'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const prettifyTime = require('./prettify-time')
|
||||
const {
|
||||
TIMESTAMP_KEY
|
||||
} = require('../constants')
|
||||
const context = {
|
||||
timestampKey: TIMESTAMP_KEY,
|
||||
translateTime: true,
|
||||
customPrettifiers: {}
|
||||
}
|
||||
|
||||
test('returns `undefined` if `time` or `timestamp` not in log', t => {
|
||||
const str = prettifyTime({ log: {}, context })
|
||||
t.assert.strictEqual(str, undefined)
|
||||
})
|
||||
|
||||
test('returns prettified formatted time from custom field', t => {
|
||||
const log = { customtime: 1554642900000 }
|
||||
let str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
timestampKey: 'customtime'
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[13:15:00.000]')
|
||||
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: false,
|
||||
timestampKey: 'customtime'
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[1554642900000]')
|
||||
})
|
||||
|
||||
test('returns prettified formatted time', t => {
|
||||
let log = { time: 1554642900000 }
|
||||
let str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[13:15:00.000]')
|
||||
|
||||
log = { timestamp: 1554642900000 }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[13:15:00.000]')
|
||||
|
||||
log = { time: '2019-04-07T09:15:00.000-04:00' }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[13:15:00.000]')
|
||||
|
||||
log = { timestamp: '2019-04-07T09:15:00.000-04:00' }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[13:15:00.000]')
|
||||
|
||||
log = { time: 1554642900000 }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: 'd mmm yyyy H:MM'
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[7 Apr 2019 13:15]')
|
||||
|
||||
log = { timestamp: 1554642900000 }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: 'd mmm yyyy H:MM'
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[7 Apr 2019 13:15]')
|
||||
|
||||
log = { time: '2019-04-07T09:15:00.000-04:00' }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: 'd mmm yyyy H:MM'
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[7 Apr 2019 13:15]')
|
||||
|
||||
log = { timestamp: '2019-04-07T09:15:00.000-04:00' }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: 'd mmm yyyy H:MM'
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[7 Apr 2019 13:15]')
|
||||
})
|
||||
|
||||
test('passes through value', t => {
|
||||
let log = { time: 1554642900000 }
|
||||
let str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: undefined
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[1554642900000]')
|
||||
|
||||
log = { timestamp: 1554642900000 }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: undefined
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[1554642900000]')
|
||||
|
||||
log = { time: '2019-04-07T09:15:00.000-04:00' }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: undefined
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[2019-04-07T09:15:00.000-04:00]')
|
||||
|
||||
log = { timestamp: '2019-04-07T09:15:00.000-04:00' }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: undefined
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[2019-04-07T09:15:00.000-04:00]')
|
||||
})
|
||||
|
||||
test('handles the 0 timestamp', t => {
|
||||
let log = { time: 0 }
|
||||
let str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: undefined
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[0]')
|
||||
|
||||
log = { timestamp: 0 }
|
||||
str = prettifyTime({
|
||||
log,
|
||||
context: {
|
||||
...context,
|
||||
translateTime: undefined
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, '[0]')
|
||||
})
|
||||
|
||||
test('works with epoch as a number or string', (t) => {
|
||||
t.plan(3)
|
||||
const epoch = 1522431328992
|
||||
const asNumber = prettifyTime({
|
||||
log: { time: epoch, msg: 'foo' },
|
||||
context: {
|
||||
...context,
|
||||
translateTime: true
|
||||
}
|
||||
})
|
||||
const asString = prettifyTime({
|
||||
log: { time: `${epoch}`, msg: 'foo' },
|
||||
context: {
|
||||
...context,
|
||||
translateTime: true
|
||||
}
|
||||
})
|
||||
const invalid = prettifyTime({
|
||||
log: { time: '2 days ago', msg: 'foo' },
|
||||
context: {
|
||||
...context,
|
||||
translateTime: true
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(asString, '[17:35:28.992]')
|
||||
t.assert.strictEqual(asNumber, '[17:35:28.992]')
|
||||
t.assert.strictEqual(invalid, '[2 days ago]')
|
||||
})
|
||||
|
||||
test('uses custom prettifier', t => {
|
||||
const str = prettifyTime({
|
||||
log: { time: 0 },
|
||||
context: {
|
||||
...context,
|
||||
customPrettifiers: {
|
||||
time () {
|
||||
return 'done'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
t.assert.strictEqual(str, 'done')
|
||||
})
|
||||
@@ -0,0 +1,188 @@
|
||||
import {Buffer} from 'buffer';
|
||||
import * as BufferLayout from '@solana/buffer-layout';
|
||||
|
||||
import {VoteAuthorizeWithSeedArgs} from './programs/vote';
|
||||
|
||||
/**
|
||||
* Layout for a public key
|
||||
*/
|
||||
export const publicKey = (property: string = 'publicKey') => {
|
||||
return BufferLayout.blob(32, property);
|
||||
};
|
||||
|
||||
/**
|
||||
* Layout for a signature
|
||||
*/
|
||||
export const signature = (property: string = 'signature') => {
|
||||
return BufferLayout.blob(64, property);
|
||||
};
|
||||
|
||||
/**
|
||||
* Layout for a 64bit unsigned value
|
||||
*/
|
||||
export const uint64 = (property: string = 'uint64') => {
|
||||
return BufferLayout.blob(8, property);
|
||||
};
|
||||
|
||||
interface IRustStringShim
|
||||
extends Omit<
|
||||
BufferLayout.Structure<
|
||||
Readonly<{
|
||||
length: number;
|
||||
lengthPadding: number;
|
||||
chars: Uint8Array;
|
||||
}>
|
||||
>,
|
||||
'decode' | 'encode' | 'replicate'
|
||||
> {
|
||||
alloc: (str: string) => number;
|
||||
decode: (b: Uint8Array, offset?: number) => string;
|
||||
encode: (str: string, b: Uint8Array, offset?: number) => number;
|
||||
replicate: (property: string) => this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout for a Rust String type
|
||||
*/
|
||||
export const rustString = (
|
||||
property: string = 'string',
|
||||
): BufferLayout.Layout<string> => {
|
||||
const rsl = BufferLayout.struct<
|
||||
Readonly<{
|
||||
length?: number;
|
||||
lengthPadding?: number;
|
||||
chars: Uint8Array;
|
||||
}>
|
||||
>(
|
||||
[
|
||||
BufferLayout.u32('length'),
|
||||
BufferLayout.u32('lengthPadding'),
|
||||
BufferLayout.blob(BufferLayout.offset(BufferLayout.u32(), -8), 'chars'),
|
||||
],
|
||||
property,
|
||||
);
|
||||
const _decode = rsl.decode.bind(rsl);
|
||||
const _encode = rsl.encode.bind(rsl);
|
||||
|
||||
const rslShim = rsl as unknown as IRustStringShim;
|
||||
|
||||
rslShim.decode = (b: Uint8Array, offset?: number) => {
|
||||
const data = _decode(b, offset);
|
||||
return data['chars'].toString();
|
||||
};
|
||||
|
||||
rslShim.encode = (str: string, b: Uint8Array, offset?: number) => {
|
||||
const data = {
|
||||
chars: Buffer.from(str, 'utf8'),
|
||||
};
|
||||
return _encode(data, b, offset);
|
||||
};
|
||||
|
||||
rslShim.alloc = (str: string) => {
|
||||
return (
|
||||
BufferLayout.u32().span +
|
||||
BufferLayout.u32().span +
|
||||
Buffer.from(str, 'utf8').length
|
||||
);
|
||||
};
|
||||
|
||||
return rslShim;
|
||||
};
|
||||
|
||||
/**
|
||||
* Layout for an Authorized object
|
||||
*/
|
||||
export const authorized = (property: string = 'authorized') => {
|
||||
return BufferLayout.struct<
|
||||
Readonly<{
|
||||
staker: Uint8Array;
|
||||
withdrawer: Uint8Array;
|
||||
}>
|
||||
>([publicKey('staker'), publicKey('withdrawer')], property);
|
||||
};
|
||||
|
||||
/**
|
||||
* Layout for a Lockup object
|
||||
*/
|
||||
export const lockup = (property: string = 'lockup') => {
|
||||
return BufferLayout.struct<
|
||||
Readonly<{
|
||||
custodian: Uint8Array;
|
||||
epoch: number;
|
||||
unixTimestamp: number;
|
||||
}>
|
||||
>(
|
||||
[
|
||||
BufferLayout.ns64('unixTimestamp'),
|
||||
BufferLayout.ns64('epoch'),
|
||||
publicKey('custodian'),
|
||||
],
|
||||
property,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Layout for a VoteInit object
|
||||
*/
|
||||
export const voteInit = (property: string = 'voteInit') => {
|
||||
return BufferLayout.struct<
|
||||
Readonly<{
|
||||
authorizedVoter: Uint8Array;
|
||||
authorizedWithdrawer: Uint8Array;
|
||||
commission: number;
|
||||
nodePubkey: Uint8Array;
|
||||
}>
|
||||
>(
|
||||
[
|
||||
publicKey('nodePubkey'),
|
||||
publicKey('authorizedVoter'),
|
||||
publicKey('authorizedWithdrawer'),
|
||||
BufferLayout.u8('commission'),
|
||||
],
|
||||
property,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Layout for a VoteAuthorizeWithSeedArgs object
|
||||
*/
|
||||
export const voteAuthorizeWithSeedArgs = (
|
||||
property: string = 'voteAuthorizeWithSeedArgs',
|
||||
) => {
|
||||
return BufferLayout.struct<VoteAuthorizeWithSeedArgs>(
|
||||
[
|
||||
BufferLayout.u32('voteAuthorizationType'),
|
||||
publicKey('currentAuthorityDerivedKeyOwnerPubkey'),
|
||||
rustString('currentAuthorityDerivedKeySeed'),
|
||||
publicKey('newAuthorized'),
|
||||
],
|
||||
property,
|
||||
);
|
||||
};
|
||||
|
||||
export function getAlloc(type: any, fields: any): number {
|
||||
const getItemAlloc = (item: any): number => {
|
||||
if (item.span >= 0) {
|
||||
return item.span;
|
||||
} else if (typeof item.alloc === 'function') {
|
||||
return item.alloc(fields[item.property]);
|
||||
} else if ('count' in item && 'elementLayout' in item) {
|
||||
const field = fields[item.property];
|
||||
if (Array.isArray(field)) {
|
||||
return field.length * getItemAlloc(item.elementLayout);
|
||||
}
|
||||
} else if ('fields' in item) {
|
||||
// This is a `Structure` whose size needs to be recursively measured.
|
||||
return getAlloc({layout: item}, fields[item.property]);
|
||||
}
|
||||
// Couldn't determine allocated size of layout
|
||||
return 0;
|
||||
};
|
||||
|
||||
let alloc = 0;
|
||||
type.layout.fields.forEach((item: any) => {
|
||||
alloc += getItemAlloc(item);
|
||||
});
|
||||
|
||||
return alloc;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
function _assert_this_initialized(self) {
|
||||
if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
||||
|
||||
return self;
|
||||
}
|
||||
export { _assert_this_initialized as _ };
|
||||
@@ -0,0 +1,26 @@
|
||||
/*! *****************************************************************************
|
||||
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="es2021" />
|
||||
/// <reference lib="es2022.array" />
|
||||
/// <reference lib="es2022.error" />
|
||||
/// <reference lib="es2022.intl" />
|
||||
/// <reference lib="es2022.object" />
|
||||
/// <reference lib="es2022.sharedmemory" />
|
||||
/// <reference lib="es2022.string" />
|
||||
/// <reference lib="es2022.regexp" />
|
||||
@@ -0,0 +1,27 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import * as z from "../index.js";
|
||||
|
||||
describe("z.describe() check", () => {
|
||||
it("registers description in globalRegistry", () => {
|
||||
const schema = z.string().check(z.describe("A string"));
|
||||
expect(z.globalRegistry.get(schema)?.description).toBe("A string");
|
||||
});
|
||||
});
|
||||
|
||||
describe("z.meta() check", () => {
|
||||
it("registers metadata in globalRegistry", () => {
|
||||
const schema = z.number().check(z.meta({ title: "Age", description: "User's age" }));
|
||||
const meta = z.globalRegistry.get(schema);
|
||||
expect(meta?.title).toBe("Age");
|
||||
expect(meta?.description).toBe("User's age");
|
||||
});
|
||||
});
|
||||
|
||||
describe("combined usage", () => {
|
||||
it("works with multiple checks", () => {
|
||||
const schema = z.string().check(z.describe("Email address"), z.meta({ title: "Email" }));
|
||||
const meta = z.globalRegistry.get(schema);
|
||||
expect(meta?.description).toBe("Email address");
|
||||
expect(meta?.title).toBe("Email");
|
||||
});
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,532 @@
|
||||
import { c as createSimpleStackTrace } from './chunk-helpers.js';
|
||||
import { mockObject } from './index.js';
|
||||
import { M as MockerRegistry, R as RedirectedModule, A as AutomockedModule } from './chunk-registry.js';
|
||||
import { e as extname, j as join } from './chunk-pathe.M-eThtNZ.js';
|
||||
|
||||
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
||||
function normalizeWindowsPath(input = "") {
|
||||
if (!input) {
|
||||
return input;
|
||||
}
|
||||
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
||||
}
|
||||
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
||||
function cwd() {
|
||||
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
||||
return process.cwd().replace(/\\/g, "/");
|
||||
}
|
||||
return "/";
|
||||
}
|
||||
const resolve = function(...arguments_) {
|
||||
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
||||
let resolvedPath = "";
|
||||
let resolvedAbsolute = false;
|
||||
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
||||
const path = index >= 0 ? arguments_[index] : cwd();
|
||||
if (!path || path.length === 0) {
|
||||
continue;
|
||||
}
|
||||
resolvedPath = `${path}/${resolvedPath}`;
|
||||
resolvedAbsolute = isAbsolute(path);
|
||||
}
|
||||
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
||||
if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
|
||||
return `/${resolvedPath}`;
|
||||
}
|
||||
return resolvedPath.length > 0 ? resolvedPath : ".";
|
||||
};
|
||||
function normalizeString(path, allowAboveRoot) {
|
||||
let res = "";
|
||||
let lastSegmentLength = 0;
|
||||
let lastSlash = -1;
|
||||
let dots = 0;
|
||||
let char = null;
|
||||
for (let index = 0; index <= path.length; ++index) {
|
||||
if (index < path.length) {
|
||||
char = path[index];
|
||||
} else if (char === "/") {
|
||||
break;
|
||||
} else {
|
||||
char = "/";
|
||||
}
|
||||
if (char === "/") {
|
||||
if (lastSlash === index - 1 || dots === 1);
|
||||
else if (dots === 2) {
|
||||
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
||||
if (res.length > 2) {
|
||||
const lastSlashIndex = res.lastIndexOf("/");
|
||||
if (lastSlashIndex === -1) {
|
||||
res = "";
|
||||
lastSegmentLength = 0;
|
||||
} else {
|
||||
res = res.slice(0, lastSlashIndex);
|
||||
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
||||
}
|
||||
lastSlash = index;
|
||||
dots = 0;
|
||||
continue;
|
||||
} else if (res.length > 0) {
|
||||
res = "";
|
||||
lastSegmentLength = 0;
|
||||
lastSlash = index;
|
||||
dots = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (allowAboveRoot) {
|
||||
res += res.length > 0 ? "/.." : "..";
|
||||
lastSegmentLength = 2;
|
||||
}
|
||||
} else {
|
||||
if (res.length > 0) {
|
||||
res += `/${path.slice(lastSlash + 1, index)}`;
|
||||
} else {
|
||||
res = path.slice(lastSlash + 1, index);
|
||||
}
|
||||
lastSegmentLength = index - lastSlash - 1;
|
||||
}
|
||||
lastSlash = index;
|
||||
dots = 0;
|
||||
} else if (char === "." && dots !== -1) {
|
||||
++dots;
|
||||
} else {
|
||||
dots = -1;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
const isAbsolute = function(p) {
|
||||
return _IS_ABSOLUTE_RE.test(p);
|
||||
};
|
||||
|
||||
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var intToChar = new Uint8Array(64);
|
||||
var charToInt = new Uint8Array(128);
|
||||
for (let i = 0; i < chars.length; i++) {
|
||||
const c = chars.charCodeAt(i);
|
||||
intToChar[i] = c;
|
||||
charToInt[c] = i;
|
||||
}
|
||||
const CHROME_IE_STACK_REGEXP = /^\s*at .*(?:\S:\d+|\(native\))/m;
|
||||
const SAFARI_NATIVE_CODE_REGEXP = /^(?:eval@)?(?:\[native code\])?$/;
|
||||
const NOW_LENGTH = Date.now().toString().length;
|
||||
const REGEXP_VITEST = new RegExp(`vitest=\\d{${NOW_LENGTH}}`);
|
||||
function extractLocation(urlLike) {
|
||||
// Fail-fast but return locations like "(native)"
|
||||
if (!urlLike.includes(":")) {
|
||||
return [urlLike];
|
||||
}
|
||||
const regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/;
|
||||
const parts = regExp.exec(urlLike.replace(/^\(|\)$/g, ""));
|
||||
if (!parts) {
|
||||
return [urlLike];
|
||||
}
|
||||
let url = parts[1];
|
||||
if (url.startsWith("async ")) {
|
||||
url = url.slice(6);
|
||||
}
|
||||
if (url.startsWith("http:") || url.startsWith("https:")) {
|
||||
const urlObj = new URL(url);
|
||||
urlObj.searchParams.delete("import");
|
||||
urlObj.searchParams.delete("browserv");
|
||||
url = urlObj.pathname + urlObj.hash + urlObj.search;
|
||||
}
|
||||
if (url.startsWith("/@fs/")) {
|
||||
const isWindows = /^\/@fs\/[a-zA-Z]:\//.test(url);
|
||||
url = url.slice(isWindows ? 5 : 4);
|
||||
}
|
||||
if (url.includes("vitest=")) {
|
||||
url = url.replace(REGEXP_VITEST, "").replace(/[?&]$/, "");
|
||||
}
|
||||
return [
|
||||
url,
|
||||
parts[2] || undefined,
|
||||
parts[3] || undefined
|
||||
];
|
||||
}
|
||||
function parseSingleFFOrSafariStack(raw) {
|
||||
let line = raw.trim();
|
||||
if (SAFARI_NATIVE_CODE_REGEXP.test(line)) {
|
||||
return null;
|
||||
}
|
||||
if (line.includes(" > eval")) {
|
||||
line = line.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, ":$1");
|
||||
}
|
||||
// Early return for lines that don't look like Firefox/Safari stack traces
|
||||
// Firefox/Safari stack traces must contain '@' and should have location info after it
|
||||
if (!line.includes("@")) {
|
||||
return null;
|
||||
}
|
||||
// Find the correct @ that separates function name from location
|
||||
// For cases like '@https://@fs/path' or 'functionName@https://@fs/path'
|
||||
// we need to find the first @ that precedes a valid location (containing :)
|
||||
let atIndex = -1;
|
||||
let locationPart = "";
|
||||
let functionName;
|
||||
// Try each @ from left to right to find the one that gives us a valid location
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
if (line[i] === "@") {
|
||||
const candidateLocation = line.slice(i + 1);
|
||||
// Minimum length 3 for valid location: 1 for filename + 1 for colon + 1 for line number (e.g., "a:1")
|
||||
if (candidateLocation.includes(":") && candidateLocation.length >= 3) {
|
||||
atIndex = i;
|
||||
locationPart = candidateLocation;
|
||||
functionName = i > 0 ? line.slice(0, i) : undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Validate we found a valid location with minimum length (filename:line format)
|
||||
if (atIndex === -1 || !locationPart.includes(":") || locationPart.length < 3) {
|
||||
return null;
|
||||
}
|
||||
const [url, lineNumber, columnNumber] = extractLocation(locationPart);
|
||||
if (!url || !lineNumber || !columnNumber) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
file: url,
|
||||
method: functionName || "",
|
||||
line: Number.parseInt(lineNumber),
|
||||
column: Number.parseInt(columnNumber)
|
||||
};
|
||||
}
|
||||
function parseSingleStack(raw) {
|
||||
const line = raw.trim();
|
||||
if (!CHROME_IE_STACK_REGEXP.test(line)) {
|
||||
return parseSingleFFOrSafariStack(line);
|
||||
}
|
||||
return parseSingleV8Stack(line);
|
||||
}
|
||||
// Based on https://github.com/stacktracejs/error-stack-parser
|
||||
// Credit to stacktracejs
|
||||
function parseSingleV8Stack(raw) {
|
||||
let line = raw.trim();
|
||||
if (!CHROME_IE_STACK_REGEXP.test(line)) {
|
||||
return null;
|
||||
}
|
||||
if (line.includes("(eval ")) {
|
||||
line = line.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
|
||||
}
|
||||
let sanitizedLine = line.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
|
||||
// capture and preserve the parenthesized location "(/foo/my bar.js:12:87)" in
|
||||
// case it has spaces in it, as the string is split on \s+ later on
|
||||
const location = sanitizedLine.match(/ (\(.+\)$)/);
|
||||
// remove the parenthesized location from the line, if it was matched
|
||||
sanitizedLine = location ? sanitizedLine.replace(location[0], "") : sanitizedLine;
|
||||
// if a location was matched, pass it to extractLocation() otherwise pass all sanitizedLine
|
||||
// because this line doesn't have function name
|
||||
const [url, lineNumber, columnNumber] = extractLocation(location ? location[1] : sanitizedLine);
|
||||
let method = location && sanitizedLine || "";
|
||||
let file = url && ["eval", "<anonymous>"].includes(url) ? undefined : url;
|
||||
if (!file || !lineNumber || !columnNumber) {
|
||||
return null;
|
||||
}
|
||||
if (method.startsWith("async ")) {
|
||||
method = method.slice(6);
|
||||
}
|
||||
if (file.startsWith("file://")) {
|
||||
file = file.slice(7);
|
||||
}
|
||||
// normalize Windows path (\ -> /)
|
||||
file = file.startsWith("node:") || file.startsWith("internal:") ? file : resolve(file);
|
||||
if (method) {
|
||||
method = method.replace(/\(0\s?,\s?__vite_ssr_import_\d+__.(\w+)\)/g, "$1").replace(/__(vite_ssr_import|vi_import)_\d+__\./g, "").replace(/(Object\.)?__vite_ssr_export_default__\s?/g, "");
|
||||
}
|
||||
return {
|
||||
method,
|
||||
file,
|
||||
line: Number.parseInt(lineNumber),
|
||||
column: Number.parseInt(columnNumber)
|
||||
};
|
||||
}
|
||||
|
||||
function createCompilerHints(options) {
|
||||
const globalThisAccessor = options?.globalThisKey || "__vitest_mocker__";
|
||||
function _mocker() {
|
||||
// @ts-expect-error injected by the plugin
|
||||
return typeof globalThis[globalThisAccessor] !== "undefined" ? globalThis[globalThisAccessor] : new Proxy({}, { get(_, name) {
|
||||
throw new Error("Vitest mocker was not initialized in this environment. " + `vi.${String(name)}() is forbidden.`);
|
||||
} });
|
||||
}
|
||||
return {
|
||||
hoisted(factory) {
|
||||
if (typeof factory !== "function") {
|
||||
throw new TypeError(`vi.hoisted() expects a function, but received a ${typeof factory}`);
|
||||
}
|
||||
return factory();
|
||||
},
|
||||
mock(path, factory) {
|
||||
if (typeof path !== "string") {
|
||||
throw new TypeError(`vi.mock() expects a string path, but received a ${typeof path}`);
|
||||
}
|
||||
const importer = getImporter("mock");
|
||||
_mocker().queueMock(path, importer, typeof factory === "function" ? () => factory(() => _mocker().importActual(path, importer)) : factory);
|
||||
},
|
||||
unmock(path) {
|
||||
if (typeof path !== "string") {
|
||||
throw new TypeError(`vi.unmock() expects a string path, but received a ${typeof path}`);
|
||||
}
|
||||
_mocker().queueUnmock(path, getImporter("unmock"));
|
||||
},
|
||||
doMock(path, factory) {
|
||||
if (typeof path !== "string") {
|
||||
throw new TypeError(`vi.doMock() expects a string path, but received a ${typeof path}`);
|
||||
}
|
||||
const importer = getImporter("doMock");
|
||||
_mocker().queueMock(path, importer, typeof factory === "function" ? () => factory(() => _mocker().importActual(path, importer)) : factory);
|
||||
},
|
||||
doUnmock(path) {
|
||||
if (typeof path !== "string") {
|
||||
throw new TypeError(`vi.doUnmock() expects a string path, but received a ${typeof path}`);
|
||||
}
|
||||
_mocker().queueUnmock(path, getImporter("doUnmock"));
|
||||
},
|
||||
async importActual(path) {
|
||||
return _mocker().importActual(path, getImporter("importActual"));
|
||||
},
|
||||
async importMock(path) {
|
||||
return _mocker().importMock(path, getImporter("importMock"));
|
||||
}
|
||||
};
|
||||
}
|
||||
function getImporter(name) {
|
||||
const stackTrace = /* @__PURE__ */ createSimpleStackTrace({ stackTraceLimit: 5 });
|
||||
const stackArray = stackTrace.split("\n");
|
||||
// if there is no message in a stack trace, use the item - 1
|
||||
const importerStackIndex = stackArray.findIndex((stack) => {
|
||||
return stack.includes(` at Object.${name}`) || stack.includes(`${name}@`);
|
||||
});
|
||||
const stack = /* @__PURE__ */ parseSingleStack(stackArray[importerStackIndex + 1]);
|
||||
return stack?.file || "";
|
||||
}
|
||||
|
||||
const hot = import.meta.hot || {
|
||||
on: warn,
|
||||
off: warn,
|
||||
send: warn
|
||||
};
|
||||
function warn() {
|
||||
console.warn("Vitest mocker cannot work if Vite didn't establish WS connection.");
|
||||
}
|
||||
function rpc(event, data) {
|
||||
hot.send(event, data);
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
reject(new Error(`Failed to resolve ${event} in time`));
|
||||
}, 5e3);
|
||||
hot.on(`${event}:result`, function r(data) {
|
||||
resolve(data);
|
||||
clearTimeout(timeout);
|
||||
hot.off(`${event}:result`, r);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const { now } = Date;
|
||||
class ModuleMocker {
|
||||
registry = new MockerRegistry();
|
||||
queue = new Set();
|
||||
mockedIds = new Set();
|
||||
constructor(interceptor, rpc, createMockInstance, config) {
|
||||
this.interceptor = interceptor;
|
||||
this.rpc = rpc;
|
||||
this.createMockInstance = createMockInstance;
|
||||
this.config = config;
|
||||
}
|
||||
async prepare() {
|
||||
if (!this.queue.size) {
|
||||
return;
|
||||
}
|
||||
await Promise.all([...this.queue.values()]);
|
||||
}
|
||||
async resolveFactoryModule(id) {
|
||||
const mock = this.registry.get(id);
|
||||
if (!mock || mock.type !== "manual") {
|
||||
throw new Error(`Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`);
|
||||
}
|
||||
const result = await mock.resolve();
|
||||
return result;
|
||||
}
|
||||
getFactoryModule(id) {
|
||||
const mock = this.registry.get(id);
|
||||
if (!mock || mock.type !== "manual") {
|
||||
throw new Error(`Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`);
|
||||
}
|
||||
if (!mock.cache) {
|
||||
throw new Error(`Mock ${id} wasn't resolved. This is probably a Vitest error. Please, open a new issue with reproduction.`);
|
||||
}
|
||||
return mock.cache;
|
||||
}
|
||||
async invalidate() {
|
||||
const ids = Array.from(this.mockedIds);
|
||||
if (!ids.length) {
|
||||
return;
|
||||
}
|
||||
await this.rpc.invalidate(ids);
|
||||
await this.interceptor.invalidate();
|
||||
this.registry.clear();
|
||||
}
|
||||
async importActual(id, importer) {
|
||||
const resolved = await this.rpc.resolveId(id, importer);
|
||||
if (resolved == null) {
|
||||
throw new Error(`[vitest] Cannot resolve "${id}" imported from "${importer}"`);
|
||||
}
|
||||
const ext = extname(resolved.id);
|
||||
const url = new URL(resolved.url, this.getBaseUrl());
|
||||
const query = `_vitest_original&ext${ext}`;
|
||||
const actualUrl = `${url.pathname}${url.search ? `${url.search}&${query}` : `?${query}`}${url.hash}`;
|
||||
return this.wrapDynamicImport(() => import(
|
||||
/* @vite-ignore */
|
||||
actualUrl
|
||||
)).then((mod) => {
|
||||
if (!resolved.optimized || typeof mod.default === "undefined") {
|
||||
return mod;
|
||||
}
|
||||
// vite injects this helper for optimized modules, so we try to follow the same behavior
|
||||
const m = mod.default;
|
||||
return m?.__esModule ? m : {
|
||||
...typeof m === "object" && !Array.isArray(m) || typeof m === "function" ? m : {},
|
||||
default: m
|
||||
};
|
||||
});
|
||||
}
|
||||
getBaseUrl() {
|
||||
return location.href;
|
||||
}
|
||||
async importMock(rawId, importer) {
|
||||
await this.prepare();
|
||||
const { resolvedId, resolvedUrl, redirectUrl } = await this.rpc.resolveMock(rawId, importer, { mock: "auto" });
|
||||
const mockUrl = this.resolveMockPath(cleanVersion(resolvedUrl));
|
||||
let mock = this.registry.get(mockUrl);
|
||||
if (!mock) {
|
||||
if (redirectUrl) {
|
||||
const resolvedRedirect = new URL(this.resolveMockPath(cleanVersion(redirectUrl)), this.getBaseUrl()).toString();
|
||||
mock = new RedirectedModule(rawId, resolvedId, mockUrl, resolvedRedirect);
|
||||
} else {
|
||||
mock = new AutomockedModule(rawId, resolvedId, mockUrl);
|
||||
}
|
||||
}
|
||||
if (mock.type === "manual") {
|
||||
return await mock.resolve();
|
||||
}
|
||||
if (mock.type === "automock" || mock.type === "autospy") {
|
||||
const url = new URL(`/@id/${resolvedId}`, this.getBaseUrl());
|
||||
const query = url.search ? `${url.search}&t=${now()}` : `?t=${now()}`;
|
||||
const moduleObject = await import(
|
||||
/* @vite-ignore */
|
||||
`${url.pathname}${query}&mock=${mock.type}${url.hash}`
|
||||
);
|
||||
return this.mockObject(moduleObject, mock.type);
|
||||
}
|
||||
return import(
|
||||
/* @vite-ignore */
|
||||
mock.redirect
|
||||
);
|
||||
}
|
||||
mockObject(object, mockExportsOrModuleType, moduleType) {
|
||||
let mockExports;
|
||||
if (mockExportsOrModuleType === "automock" || mockExportsOrModuleType === "autospy") {
|
||||
moduleType = mockExportsOrModuleType;
|
||||
mockExports = undefined;
|
||||
} else {
|
||||
mockExports = mockExportsOrModuleType;
|
||||
}
|
||||
moduleType ??= "automock";
|
||||
const result = mockObject({
|
||||
globalConstructors: {
|
||||
Object,
|
||||
Function,
|
||||
Array,
|
||||
Map,
|
||||
RegExp
|
||||
},
|
||||
createMockInstance: this.createMockInstance,
|
||||
type: moduleType
|
||||
}, object, mockExports);
|
||||
return result;
|
||||
}
|
||||
getMockContext() {
|
||||
return { callstack: null };
|
||||
}
|
||||
queueMock(rawId, importer, factoryOrOptions) {
|
||||
const promise = this.rpc.resolveMock(rawId, importer, { mock: typeof factoryOrOptions === "function" ? "factory" : factoryOrOptions?.spy ? "spy" : "auto" }).then(async ({ redirectUrl, resolvedId, resolvedUrl, needsInterop, mockType }) => {
|
||||
const mockUrl = this.resolveMockPath(cleanVersion(resolvedUrl));
|
||||
this.mockedIds.add(resolvedId);
|
||||
const factory = typeof factoryOrOptions === "function" ? async () => {
|
||||
const data = await factoryOrOptions();
|
||||
// vite wraps all external modules that have "needsInterop" in a function that
|
||||
// merges all exports from default into the module object
|
||||
return needsInterop ? { default: data } : data;
|
||||
} : undefined;
|
||||
const mockRedirect = typeof redirectUrl === "string" ? new URL(this.resolveMockPath(cleanVersion(redirectUrl)), this.getBaseUrl()).toString() : null;
|
||||
let module;
|
||||
if (mockType === "manual") {
|
||||
module = this.registry.register("manual", rawId, resolvedId, mockUrl, factory);
|
||||
} else if (mockType === "autospy") {
|
||||
module = this.registry.register("autospy", rawId, resolvedId, mockUrl);
|
||||
} else if (mockType === "redirect") {
|
||||
module = this.registry.register("redirect", rawId, resolvedId, mockUrl, mockRedirect);
|
||||
} else {
|
||||
module = this.registry.register("automock", rawId, resolvedId, mockUrl);
|
||||
}
|
||||
await this.interceptor.register(module);
|
||||
}).finally(() => {
|
||||
this.queue.delete(promise);
|
||||
});
|
||||
this.queue.add(promise);
|
||||
}
|
||||
queueUnmock(id, importer) {
|
||||
const promise = this.rpc.resolveId(id, importer).then(async (resolved) => {
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
const mockUrl = this.resolveMockPath(cleanVersion(resolved.url));
|
||||
this.mockedIds.add(resolved.id);
|
||||
this.registry.delete(mockUrl);
|
||||
await this.interceptor.delete(mockUrl);
|
||||
}).finally(() => {
|
||||
this.queue.delete(promise);
|
||||
});
|
||||
this.queue.add(promise);
|
||||
}
|
||||
// We need to await mock registration before importing the actual module
|
||||
// In case there is a mocked module in the import chain
|
||||
wrapDynamicImport(moduleFactory) {
|
||||
if (typeof moduleFactory === "function") {
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
this.prepare().finally(() => {
|
||||
moduleFactory().then(resolve, reject);
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
return moduleFactory;
|
||||
}
|
||||
getMockedModuleById(id) {
|
||||
return this.registry.getById(id);
|
||||
}
|
||||
reset() {
|
||||
this.registry.clear();
|
||||
this.mockedIds.clear();
|
||||
this.queue.clear();
|
||||
}
|
||||
resolveMockPath(path) {
|
||||
const config = this.config;
|
||||
const fsRoot = join("/@fs/", config.root);
|
||||
// URL can be /file/path.js, but path is resolved to /file/path
|
||||
if (path.startsWith(config.root)) {
|
||||
return path.slice(config.root.length);
|
||||
}
|
||||
if (path.startsWith(fsRoot)) {
|
||||
return path.slice(fsRoot.length);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
const versionRegexp = /(\?|&)v=\w{8}/;
|
||||
function cleanVersion(url) {
|
||||
return url.replace(versionRegexp, "");
|
||||
}
|
||||
|
||||
export { ModuleMocker as M, createCompilerHints as c, hot as h, rpc as r };
|
||||
@@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = require('./lib');
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Toru Nagashima
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/abstract/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC;AAEjC,oDAAoD;AACpD,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;AACxB,oDAAoD;AACpD,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;AAChC,oDAAoD;AACpD,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;AAC5B,oDAAoD;AACpD,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;AAE5B,oDAAoD;AACpD,eAAO,MAAM,MAAM,EAAE,OAAO,CAAC,CAAC,MAAiB,CAAC;AAChD,oDAAoD;AACpD,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,CAAC,OAAmB,CAAC;AACnD,oDAAoD;AACpD,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,CAAC,UAAyB,CAAC;AAC5D,oDAAoD;AACpD,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,CAAC,WAA2B,CAAC;AAC/D,oDAAoD;AACpD,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,CAAC,WAA2B,CAAC;AAC/D,oDAAoD;AACpD,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,CAAC,UAAyB,CAAC;AAC5D,oDAAoD;AACpD,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,CAAC,OAAmB,CAAC;AACnD,oDAAoD;AACpD,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,CAAC,WAA2B,CAAC;AAC/D,oDAAoD;AACpD,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,CAAC,WAA2B,CAAC;AAE/D,oDAAoD;AACpD,eAAO,MAAM,KAAK,EAAE,OAAO,CAAC,CAAC,KAAe,CAAC;AAC7C,oDAAoD;AACpD,eAAO,MAAM,mBAAmB,EAAE,OAAO,CAAC,CAAC,mBAA2C,CAAC;AACvF,oDAAoD;AACpD,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,CAAC,WAA2B,CAAC;AAC/D,oDAAoD;AACpD,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,CAAC,eAAmC,CAAC;AAC3E,oDAAoD;AACpD,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,CAAC,eAAmC,CAAC;AAC3E,oDAAoD;AACpD,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,CAAC,eAAmC,CAAC;AAC3E,oDAAoD;AACpD,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,CAAC,eAAmC,CAAC;AAC3E,oDAAoD;AACpD,eAAO,MAAM,kBAAkB,EAAE,OAAO,CAAC,CAAC,kBAAyC,CAAC;AACpF,oDAAoD;AACpD,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,CAAC,WAA2B,CAAC;AAC/D,oDAAoD;AACpD,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,CAAC,UAAyB,CAAC;AAC5D,oDAAoD;AACpD,eAAO,MAAM,SAAS,EAAE,OAAO,CAAC,CAAC,SAAuB,CAAC;AACzD,oDAAoD;AACpD,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,CAAC,YAA6B,CAAC;AAClE,oDAAoD;AACpD,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,CAAC,OAAmB,CAAC;AACnD,oDAAoD;AACpD,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAqB,CAAC;AACtD,oDAAoD;AACpD,eAAO,MAAM,MAAM,EAAE,OAAO,CAAC,CAAC,MAAiB,CAAC;AAChD,oDAAoD;AACpD,eAAO,MAAM,MAAM,EAAE,OAAO,CAAC,CAAC,MAAiB,CAAC;AAChD,oDAAoD;AACpD,eAAO,MAAM,MAAM,EAAE,OAAO,CAAC,CAAC,MAAiB,CAAC;AAChD,oDAAoD;AACpD,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,CAAC,OAAmB,CAAC;AACnD,oDAAoD;AACpD,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,CAAC,cAAiC,CAAC;AACxE,oDAAoD;AACpD,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,CAAC,cAAiC,CAAC;AACxE,oDAAoD;AACpD,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAqB,CAAC;AACtD,oDAAoD;AACpD,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,CAAC,cAAiC,CAAC;AACxE,oDAAoD;AACpD,eAAO,MAAM,MAAM,EAAE,OAAO,CAAC,CAAC,MAAiB,CAAC"}
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Vercel, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,34 @@
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
|
||||
const writer = require('flush-write-stream')
|
||||
const pino = require('../')
|
||||
|
||||
function capture () {
|
||||
const ws = writer((chunk, enc, cb) => {
|
||||
ws.data += chunk.toString()
|
||||
cb()
|
||||
})
|
||||
ws.data = ''
|
||||
return ws
|
||||
}
|
||||
|
||||
test('pino uses LF by default', async () => {
|
||||
const stream = capture()
|
||||
const logger = pino(stream)
|
||||
logger.info('foo')
|
||||
logger.error('bar')
|
||||
assert.ok(/foo[^\r\n]+\n[^\r\n]+bar[^\r\n]+\n/.test(stream.data))
|
||||
})
|
||||
|
||||
test('pino can log CRLF', async () => {
|
||||
const stream = capture()
|
||||
const logger = pino({
|
||||
crlf: true
|
||||
}, stream)
|
||||
logger.info('foo')
|
||||
logger.error('bar')
|
||||
assert.ok(/foo[^\n]+\r\n[^\n]+bar[^\n]+\r\n/.test(stream.data))
|
||||
})
|
||||
@@ -0,0 +1,57 @@
|
||||
// @ts-ignore TS6133
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v3";
|
||||
|
||||
test("function parsing", () => {
|
||||
const schema = z.union([z.string().refine(() => false), z.number().refine(() => false)]);
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("union 2", () => {
|
||||
const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a");
|
||||
expect(result.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("return valid over invalid", () => {
|
||||
const schema = z.union([
|
||||
z.object({
|
||||
email: z.string().email(),
|
||||
}),
|
||||
z.string(),
|
||||
]);
|
||||
expect(schema.parse("asdf")).toEqual("asdf");
|
||||
expect(schema.parse({ email: "asdlkjf@lkajsdf.com" })).toEqual({
|
||||
email: "asdlkjf@lkajsdf.com",
|
||||
});
|
||||
});
|
||||
|
||||
test("return dirty result over aborted", () => {
|
||||
const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues).toEqual([
|
||||
{
|
||||
code: "custom",
|
||||
message: "Invalid input",
|
||||
path: [],
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test("options getter", async () => {
|
||||
const union = z.union([z.string(), z.number()]);
|
||||
union.options[0].parse("asdf");
|
||||
union.options[1].parse(1234);
|
||||
await union.options[0].parseAsync("asdf");
|
||||
await union.options[1].parseAsync(1234);
|
||||
});
|
||||
|
||||
test("readonly union", async () => {
|
||||
const options = [z.string(), z.number()] as const;
|
||||
const union = z.union(options);
|
||||
union.parse("asdf");
|
||||
union.parse(12);
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"for + if": {
|
||||
"name": "for + if",
|
||||
"browser": "Chrome Mobile 55.0.2883 (Android 6.0.0)",
|
||||
"suite": "itar-long",
|
||||
"hz": 26338.90022369847,
|
||||
"success": true,
|
||||
"fastest": true,
|
||||
"rme": 0.025063817288098963,
|
||||
"rhz": 1,
|
||||
"sampleSize": 193
|
||||
},
|
||||
"while + if": {
|
||||
"name": "while + if",
|
||||
"browser": "Chrome Mobile 55.0.2883 (Android 6.0.0)",
|
||||
"suite": "itar-long",
|
||||
"hz": 25959.375873252164,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.023417818686660433,
|
||||
"rhz": 0.9855907290272952,
|
||||
"sampleSize": 192
|
||||
},
|
||||
"array join": {
|
||||
"name": "array join",
|
||||
"browser": "Chrome Mobile 55.0.2883 (Android 6.0.0)",
|
||||
"suite": "itar-long",
|
||||
"hz": 25445.828238320097,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.02452188410321602,
|
||||
"rhz": 0.9660930419344225,
|
||||
"sampleSize": 191
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noFunctionConstructor" | "noImpliedEvalError", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,8 @@
|
||||
declare const _default: {
|
||||
parser: string;
|
||||
parserOptions: {
|
||||
sourceType: "module";
|
||||
};
|
||||
plugins: string[];
|
||||
};
|
||||
export = _default;
|
||||
@@ -0,0 +1,27 @@
|
||||
"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_disposable = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
const es2015_iterable_1 = require("./es2015.iterable");
|
||||
const es2015_symbol_1 = require("./es2015.symbol");
|
||||
const es2018_asynciterable_1 = require("./es2018.asynciterable");
|
||||
exports.esnext_disposable = {
|
||||
libs: [es2015_symbol_1.es2015_symbol, es2015_iterable_1.es2015_iterable, es2018_asynciterable_1.es2018_asynciterable],
|
||||
variables: [
|
||||
['SymbolConstructor', base_config_1.TYPE],
|
||||
['Disposable', base_config_1.TYPE],
|
||||
['AsyncDisposable', base_config_1.TYPE],
|
||||
['SuppressedError', base_config_1.TYPE_VALUE],
|
||||
['SuppressedErrorConstructor', base_config_1.TYPE],
|
||||
['DisposableStack', base_config_1.TYPE_VALUE],
|
||||
['DisposableStackConstructor', base_config_1.TYPE],
|
||||
['AsyncDisposableStack', base_config_1.TYPE_VALUE],
|
||||
['AsyncDisposableStackConstructor', base_config_1.TYPE],
|
||||
['IteratorObject', base_config_1.TYPE],
|
||||
['AsyncIteratorObject', base_config_1.TYPE],
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"sha256.d.ts","sourceRoot":"","sources":["src/sha256.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,MAAM,IAAI,OAAO,EACjB,MAAM,IAAI,OAAO,EACjB,MAAM,IAAI,OAAO,EACjB,MAAM,IAAI,OAAO,EAClB,MAAM,WAAW,CAAC;AACnB,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC"}
|
||||
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* @fileoverview Rule to control spacing within function calls
|
||||
* @author Matt DuVall <http://www.mattduvall.com>
|
||||
* @deprecated in ESLint v8.53.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: {
|
||||
message: "Formatting rules are being moved out of ESLint core.",
|
||||
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
|
||||
deprecatedSince: "8.53.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
message:
|
||||
"ESLint Stylistic now maintains deprecated stylistic core rules.",
|
||||
url: "https://eslint.style/guide/migration",
|
||||
plugin: {
|
||||
name: "@stylistic/eslint-plugin",
|
||||
url: "https://eslint.style",
|
||||
},
|
||||
rule: {
|
||||
name: "function-call-spacing",
|
||||
url: "https://eslint.style/rules/function-call-spacing",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Require or disallow spacing between function identifiers and their invocations",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/func-call-spacing",
|
||||
},
|
||||
|
||||
fixable: "whitespace",
|
||||
|
||||
schema: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: ["never"],
|
||||
},
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 1,
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: ["always"],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
allowNewlines: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
messages: {
|
||||
unexpectedWhitespace:
|
||||
"Unexpected whitespace between function name and paren.",
|
||||
unexpectedNewline:
|
||||
"Unexpected newline between function name and paren.",
|
||||
missing: "Missing space between function name and paren.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const never = context.options[0] !== "always";
|
||||
const allowNewlines =
|
||||
!never && context.options[1] && context.options[1].allowNewlines;
|
||||
const sourceCode = context.sourceCode;
|
||||
const text = sourceCode.getText();
|
||||
|
||||
/**
|
||||
* Check if open space is present in a function name
|
||||
* @param {ASTNode} node node to evaluate
|
||||
* @param {Token} leftToken The last token of the callee. This may be the closing parenthesis that encloses the callee.
|
||||
* @param {Token} rightToken The first token of the arguments. this is the opening parenthesis that encloses the arguments.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function checkSpacing(node, leftToken, rightToken) {
|
||||
const textBetweenTokens = text
|
||||
.slice(leftToken.range[1], rightToken.range[0])
|
||||
.replace(/\/\*.*?\*\//gu, "");
|
||||
const hasWhitespace = /\s/u.test(textBetweenTokens);
|
||||
const hasNewline =
|
||||
hasWhitespace &&
|
||||
astUtils.LINEBREAK_MATCHER.test(textBetweenTokens);
|
||||
|
||||
/*
|
||||
* never allowNewlines hasWhitespace hasNewline message
|
||||
* F F F F Missing space between function name and paren.
|
||||
* F F F T (Invalid `!hasWhitespace && hasNewline`)
|
||||
* F F T T Unexpected newline between function name and paren.
|
||||
* F F T F (OK)
|
||||
* F T T F (OK)
|
||||
* F T T T (OK)
|
||||
* F T F T (Invalid `!hasWhitespace && hasNewline`)
|
||||
* F T F F Missing space between function name and paren.
|
||||
* T T F F (Invalid `never && allowNewlines`)
|
||||
* T T F T (Invalid `!hasWhitespace && hasNewline`)
|
||||
* T T T T (Invalid `never && allowNewlines`)
|
||||
* T T T F (Invalid `never && allowNewlines`)
|
||||
* T F T F Unexpected space between function name and paren.
|
||||
* T F T T Unexpected space between function name and paren.
|
||||
* T F F T (Invalid `!hasWhitespace && hasNewline`)
|
||||
* T F F F (OK)
|
||||
*
|
||||
* T T Unexpected space between function name and paren.
|
||||
* F F Missing space between function name and paren.
|
||||
* F F T Unexpected newline between function name and paren.
|
||||
*/
|
||||
|
||||
if (never && hasWhitespace) {
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
start: leftToken.loc.end,
|
||||
end: {
|
||||
line: rightToken.loc.start.line,
|
||||
column: rightToken.loc.start.column - 1,
|
||||
},
|
||||
},
|
||||
messageId: "unexpectedWhitespace",
|
||||
fix(fixer) {
|
||||
// Don't remove comments.
|
||||
if (
|
||||
sourceCode.commentsExistBetween(
|
||||
leftToken,
|
||||
rightToken,
|
||||
)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If `?.` exists, it doesn't hide no-unexpected-multiline errors
|
||||
if (node.optional) {
|
||||
return fixer.replaceTextRange(
|
||||
[leftToken.range[1], rightToken.range[0]],
|
||||
"?.",
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only autofix if there is no newline
|
||||
* https://github.com/eslint/eslint/issues/7787
|
||||
*/
|
||||
if (hasNewline) {
|
||||
return null;
|
||||
}
|
||||
return fixer.removeRange([
|
||||
leftToken.range[1],
|
||||
rightToken.range[0],
|
||||
]);
|
||||
},
|
||||
});
|
||||
} else if (!never && !hasWhitespace) {
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
start: {
|
||||
line: leftToken.loc.end.line,
|
||||
column: leftToken.loc.end.column - 1,
|
||||
},
|
||||
end: rightToken.loc.start,
|
||||
},
|
||||
messageId: "missing",
|
||||
fix(fixer) {
|
||||
if (node.optional) {
|
||||
return null; // Not sure if inserting a space to either before/after `?.` token.
|
||||
}
|
||||
return fixer.insertTextBefore(rightToken, " ");
|
||||
},
|
||||
});
|
||||
} else if (!never && !allowNewlines && hasNewline) {
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
start: leftToken.loc.end,
|
||||
end: rightToken.loc.start,
|
||||
},
|
||||
messageId: "unexpectedNewline",
|
||||
fix(fixer) {
|
||||
/*
|
||||
* Only autofix if there is no newline
|
||||
* https://github.com/eslint/eslint/issues/7787
|
||||
* But if `?.` exists, it doesn't hide no-unexpected-multiline errors
|
||||
*/
|
||||
if (!node.optional) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Don't remove comments.
|
||||
if (
|
||||
sourceCode.commentsExistBetween(
|
||||
leftToken,
|
||||
rightToken,
|
||||
)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const range = [leftToken.range[1], rightToken.range[0]];
|
||||
const qdToken = sourceCode.getTokenAfter(leftToken);
|
||||
|
||||
if (qdToken.range[0] === leftToken.range[1]) {
|
||||
return fixer.replaceTextRange(range, "?. ");
|
||||
}
|
||||
if (qdToken.range[1] === rightToken.range[0]) {
|
||||
return fixer.replaceTextRange(range, " ?.");
|
||||
}
|
||||
return fixer.replaceTextRange(range, " ?. ");
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
"CallExpression, NewExpression"(node) {
|
||||
const lastToken = sourceCode.getLastToken(node);
|
||||
const lastCalleeToken = sourceCode.getLastToken(node.callee);
|
||||
const parenToken = sourceCode.getFirstTokenBetween(
|
||||
lastCalleeToken,
|
||||
lastToken,
|
||||
astUtils.isOpeningParenToken,
|
||||
);
|
||||
const prevToken =
|
||||
parenToken &&
|
||||
sourceCode.getTokenBefore(
|
||||
parenToken,
|
||||
astUtils.isNotQuestionDotToken,
|
||||
);
|
||||
|
||||
// Parens in NewExpression are optional
|
||||
if (!(parenToken && parenToken.range[1] < node.range[1])) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkSpacing(node, prevToken, parenToken);
|
||||
},
|
||||
|
||||
ImportExpression(node) {
|
||||
const leftToken = sourceCode.getFirstToken(node);
|
||||
const rightToken = sourceCode.getTokenAfter(leftToken);
|
||||
|
||||
checkSpacing(node, leftToken, rightToken);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @fileoverview Assertion utilities.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/**
|
||||
* Throws an error if the given condition is not truthy.
|
||||
* @param {boolean} condition The condition to check.
|
||||
* @param {string} message The message to include with the error.
|
||||
* @returns {void}
|
||||
* @throws {Error} When the condition is not truthy.
|
||||
*/
|
||||
export function assert(condition, message = "Assertion failed.") {
|
||||
if (!condition) {
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const esnext_string: LibDefinition;
|
||||
@@ -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.es2021_string = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2021_string = {
|
||||
libs: [],
|
||||
variables: [['String', base_config_1.TYPE]],
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
Copyright (c) 2015-20 [these people](https://github.com/Rich-Harris/estree-walker/graphs/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "ws",
|
||||
"version": "7.5.13",
|
||||
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
|
||||
"keywords": [
|
||||
"HyBi",
|
||||
"Push",
|
||||
"RFC-6455",
|
||||
"WebSocket",
|
||||
"WebSockets",
|
||||
"real-time"
|
||||
],
|
||||
"homepage": "https://github.com/websockets/ws",
|
||||
"bugs": "https://github.com/websockets/ws/issues",
|
||||
"repository": "websockets/ws",
|
||||
"author": "Einar Otto Stangvik <einaros@gmail.com> (http://2x.io)",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"browser": "browser.js",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"files": [
|
||||
"browser.js",
|
||||
"index.js",
|
||||
"lib/*.js"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "nyc --reporter=lcov --reporter=text mocha --throw-deprecation test/*.test.js",
|
||||
"integration": "mocha --throw-deprecation test/*.integration.js",
|
||||
"lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yaml,yml}\""
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"benchmark": "^2.1.4",
|
||||
"bufferutil": "^4.0.1",
|
||||
"eslint": "^7.2.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"mocha": "^7.0.0",
|
||||
"nyc": "^15.0.0",
|
||||
"prettier": "^2.0.5",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference no-default-lib="true"/>
|
||||
|
||||
/// <reference lib="es2023" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="webworker.importscripts" />
|
||||
/// <reference lib="scripthost" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
/// <reference lib="dom.asynciterable" />
|
||||
Reference in New Issue
Block a user