WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_update.cjs",
|
||||
"module": "../../esm/_update.js"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { DatabaseError } from './messages'
|
||||
import { serialize } from './serializer'
|
||||
import { Parser, MessageCallback } from './parser'
|
||||
|
||||
export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise<void> {
|
||||
const parser = new Parser()
|
||||
stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback))
|
||||
return new Promise((resolve) => stream.on('end', () => resolve()))
|
||||
}
|
||||
|
||||
export { serialize, DatabaseError }
|
||||
@@ -0,0 +1,431 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const tsutils = __importStar(require("ts-api-utils"));
|
||||
const ts = __importStar(require("typescript"));
|
||||
const util_1 = require("../util");
|
||||
const literalToPrimitiveTypeFlags = {
|
||||
[ts.TypeFlags.BigIntLiteral]: ts.TypeFlags.BigInt,
|
||||
[ts.TypeFlags.BooleanLiteral]: ts.TypeFlags.Boolean,
|
||||
[ts.TypeFlags.NumberLiteral]: ts.TypeFlags.Number,
|
||||
[ts.TypeFlags.StringLiteral]: ts.TypeFlags.String,
|
||||
[ts.TypeFlags.TemplateLiteral]: ts.TypeFlags.String,
|
||||
};
|
||||
const literalTypeFlags = [
|
||||
ts.TypeFlags.BigIntLiteral,
|
||||
ts.TypeFlags.BooleanLiteral,
|
||||
ts.TypeFlags.NumberLiteral,
|
||||
ts.TypeFlags.StringLiteral,
|
||||
ts.TypeFlags.TemplateLiteral,
|
||||
];
|
||||
const primitiveTypeFlags = [
|
||||
ts.TypeFlags.BigInt,
|
||||
ts.TypeFlags.Boolean,
|
||||
ts.TypeFlags.Number,
|
||||
ts.TypeFlags.String,
|
||||
];
|
||||
const primitiveTypeFlagNames = {
|
||||
[ts.TypeFlags.BigInt]: 'bigint',
|
||||
[ts.TypeFlags.Boolean]: 'boolean',
|
||||
[ts.TypeFlags.Number]: 'number',
|
||||
[ts.TypeFlags.String]: 'string',
|
||||
};
|
||||
const primitiveTypeFlagTypes = {
|
||||
bigint: ts.TypeFlags.BigIntLiteral,
|
||||
boolean: ts.TypeFlags.BooleanLiteral,
|
||||
number: ts.TypeFlags.NumberLiteral,
|
||||
string: ts.TypeFlags.StringLiteral,
|
||||
};
|
||||
const keywordNodeTypesToTsTypes = new Map([
|
||||
[utils_1.TSESTree.AST_NODE_TYPES.TSAnyKeyword, ts.TypeFlags.Any],
|
||||
[utils_1.TSESTree.AST_NODE_TYPES.TSBigIntKeyword, ts.TypeFlags.BigInt],
|
||||
[utils_1.TSESTree.AST_NODE_TYPES.TSBooleanKeyword, ts.TypeFlags.Boolean],
|
||||
[utils_1.TSESTree.AST_NODE_TYPES.TSNeverKeyword, ts.TypeFlags.Never],
|
||||
[utils_1.TSESTree.AST_NODE_TYPES.TSNumberKeyword, ts.TypeFlags.Number],
|
||||
[utils_1.TSESTree.AST_NODE_TYPES.TSStringKeyword, ts.TypeFlags.String],
|
||||
[utils_1.TSESTree.AST_NODE_TYPES.TSUnknownKeyword, ts.TypeFlags.Unknown],
|
||||
]);
|
||||
function addToMapGroup(map, key, value) {
|
||||
const existing = map.get(key);
|
||||
if (existing) {
|
||||
existing.push(value);
|
||||
}
|
||||
else {
|
||||
map.set(key, [value]);
|
||||
}
|
||||
}
|
||||
function describeLiteralType(type) {
|
||||
if (type.isStringLiteral()) {
|
||||
return JSON.stringify(type.value);
|
||||
}
|
||||
if ((0, util_1.isTypeBigIntLiteralType)(type)) {
|
||||
return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`;
|
||||
}
|
||||
if (type.isLiteral()) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
return type.value.toString();
|
||||
}
|
||||
if (tsutils.isIntrinsicErrorType(type) && type.aliasSymbol) {
|
||||
return type.aliasSymbol.escapedName.toString();
|
||||
}
|
||||
if ((0, util_1.isTypeAnyType)(type)) {
|
||||
return 'any';
|
||||
}
|
||||
if ((0, util_1.isTypeNeverType)(type)) {
|
||||
return 'never';
|
||||
}
|
||||
if ((0, util_1.isTypeUnknownType)(type)) {
|
||||
return 'unknown';
|
||||
}
|
||||
if ((0, util_1.isTypeTemplateLiteralType)(type)) {
|
||||
return 'template literal type';
|
||||
}
|
||||
if ((0, util_1.isTypeBigIntLiteralType)(type)) {
|
||||
return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`;
|
||||
}
|
||||
if (tsutils.isTrueLiteralType(type)) {
|
||||
return 'true';
|
||||
}
|
||||
if (tsutils.isFalseLiteralType(type)) {
|
||||
return 'false';
|
||||
}
|
||||
return 'literal type';
|
||||
}
|
||||
function describeLiteralTypeNode(typeNode) {
|
||||
switch (typeNode.type) {
|
||||
case utils_1.AST_NODE_TYPES.TSAnyKeyword:
|
||||
return 'any';
|
||||
case utils_1.AST_NODE_TYPES.TSBooleanKeyword:
|
||||
return 'boolean';
|
||||
case utils_1.AST_NODE_TYPES.TSNeverKeyword:
|
||||
return 'never';
|
||||
case utils_1.AST_NODE_TYPES.TSNumberKeyword:
|
||||
return 'number';
|
||||
case utils_1.AST_NODE_TYPES.TSStringKeyword:
|
||||
return 'string';
|
||||
case utils_1.AST_NODE_TYPES.TSUnknownKeyword:
|
||||
return 'unknown';
|
||||
case utils_1.AST_NODE_TYPES.TSLiteralType:
|
||||
switch (typeNode.literal.type) {
|
||||
case utils_1.TSESTree.AST_NODE_TYPES.Literal:
|
||||
switch (typeof typeNode.literal.value) {
|
||||
case 'bigint':
|
||||
return `${typeNode.literal.value < 0 ? '-' : ''}${typeNode.literal.value}n`;
|
||||
case 'string':
|
||||
return JSON.stringify(typeNode.literal.value);
|
||||
default:
|
||||
return `${typeNode.literal.value}`;
|
||||
}
|
||||
case utils_1.TSESTree.AST_NODE_TYPES.TemplateLiteral:
|
||||
return 'template literal type';
|
||||
}
|
||||
}
|
||||
return 'literal type';
|
||||
}
|
||||
function isNodeInsideReturnType(node) {
|
||||
return (node.parent.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation &&
|
||||
(0, util_1.isFunctionOrFunctionType)(node.parent.parent));
|
||||
}
|
||||
/**
|
||||
* @remarks TypeScript stores boolean types as the union false | true, always.
|
||||
*/
|
||||
function unionTypePartsUnlessBoolean(type) {
|
||||
return type.isUnion() &&
|
||||
type.types.length === 2 &&
|
||||
tsutils.isFalseLiteralType(type.types[0]) &&
|
||||
tsutils.isTrueLiteralType(type.types[1])
|
||||
? [type]
|
||||
: tsutils.unionConstituents(type);
|
||||
}
|
||||
exports.default = (0, util_1.createRule)({
|
||||
name: 'no-redundant-type-constituents',
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Disallow members of unions and intersections that do nothing or override type information',
|
||||
recommended: 'recommended',
|
||||
requiresTypeChecking: true,
|
||||
},
|
||||
messages: {
|
||||
errorTypeOverrides: `'{{typeName}}' is an 'error' type that acts as 'any' and overrides all other types in this {{container}} type.`,
|
||||
literalOverridden: `{{literal}} is overridden by {{primitive}} in this union type.`,
|
||||
overridden: `'{{typeName}}' is overridden by other types in this {{container}} type.`,
|
||||
overrides: `'{{typeName}}' overrides all other types in this {{container}} type.`,
|
||||
primitiveOverridden: `{{primitive}} is overridden by the {{literal}} in this intersection type.`,
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
create(context) {
|
||||
const services = (0, util_1.getParserServices)(context);
|
||||
const typesCache = new Map();
|
||||
function getTypeNodeTypePartFlags(typeNode) {
|
||||
const keywordTypeFlags = keywordNodeTypesToTsTypes.get(typeNode.type);
|
||||
if (keywordTypeFlags) {
|
||||
return [
|
||||
{
|
||||
typeFlags: keywordTypeFlags,
|
||||
typeName: describeLiteralTypeNode(typeNode),
|
||||
},
|
||||
];
|
||||
}
|
||||
if (typeNode.type === utils_1.AST_NODE_TYPES.TSLiteralType &&
|
||||
typeNode.literal.type === utils_1.AST_NODE_TYPES.Literal) {
|
||||
return [
|
||||
{
|
||||
typeFlags: primitiveTypeFlagTypes[typeof typeNode.literal
|
||||
.value],
|
||||
typeName: describeLiteralTypeNode(typeNode),
|
||||
},
|
||||
];
|
||||
}
|
||||
if (typeNode.type === utils_1.AST_NODE_TYPES.TSUnionType) {
|
||||
return typeNode.types.flatMap(getTypeNodeTypePartFlags);
|
||||
}
|
||||
const nodeType = services.getTypeAtLocation(typeNode);
|
||||
const typeParts = unionTypePartsUnlessBoolean(nodeType);
|
||||
return typeParts.map(typePart => ({
|
||||
typeFlags: typePart.flags,
|
||||
typeName: describeLiteralType(typePart),
|
||||
}));
|
||||
}
|
||||
function getTypeNodeTypePartFlagsCached(typeNode) {
|
||||
const existing = typesCache.get(typeNode);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
const created = getTypeNodeTypePartFlags(typeNode);
|
||||
typesCache.set(typeNode, created);
|
||||
return created;
|
||||
}
|
||||
return {
|
||||
'TSIntersectionType:exit'(node) {
|
||||
const seenLiteralTypes = new Map();
|
||||
const seenPrimitiveTypes = new Map();
|
||||
const seenUnionTypes = new Map();
|
||||
function checkIntersectionBottomAndTopTypes({ typeFlags, typeName }, typeNode) {
|
||||
for (const [messageId, checkFlag] of [
|
||||
['overrides', ts.TypeFlags.Any],
|
||||
['overrides', ts.TypeFlags.Never],
|
||||
['overridden', ts.TypeFlags.Unknown],
|
||||
]) {
|
||||
if (typeFlags === checkFlag) {
|
||||
context.report({
|
||||
node: typeNode,
|
||||
messageId: typeFlags === ts.TypeFlags.Any && typeName !== 'any'
|
||||
? 'errorTypeOverrides'
|
||||
: messageId,
|
||||
data: {
|
||||
container: 'intersection',
|
||||
typeName,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (const typeNode of node.types) {
|
||||
const typePartFlags = getTypeNodeTypePartFlagsCached(typeNode);
|
||||
for (const typePart of typePartFlags) {
|
||||
if (checkIntersectionBottomAndTopTypes(typePart, typeNode)) {
|
||||
continue;
|
||||
}
|
||||
for (const literalTypeFlag of literalTypeFlags) {
|
||||
if (typePart.typeFlags === literalTypeFlag) {
|
||||
addToMapGroup(seenLiteralTypes, literalToPrimitiveTypeFlags[literalTypeFlag], typePart.typeName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const primitiveTypeFlag of primitiveTypeFlags) {
|
||||
if (typePart.typeFlags === primitiveTypeFlag) {
|
||||
addToMapGroup(seenPrimitiveTypes, primitiveTypeFlag, typeNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if any typeNode is TSTypeReference and typePartFlags have more than 1 element, than the referenced type is definitely a union.
|
||||
if (typePartFlags.length >= 2) {
|
||||
seenUnionTypes.set(typeNode, typePartFlags);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @example
|
||||
* ```ts
|
||||
* type F = "a"|2|"b";
|
||||
* type I = F & string;
|
||||
* ```
|
||||
* This function checks if all the union members of `F` are assignable to the other member of `I`. If every member is assignable, then its reported else not.
|
||||
*/
|
||||
const checkIfUnionsAreAssignable = () => {
|
||||
for (const [typeRef, typeValues] of seenUnionTypes) {
|
||||
let primitive = undefined;
|
||||
for (const { typeFlags } of typeValues) {
|
||||
if (seenPrimitiveTypes.has(literalToPrimitiveTypeFlags[typeFlags])) {
|
||||
primitive =
|
||||
literalToPrimitiveTypeFlags[typeFlags];
|
||||
}
|
||||
else {
|
||||
primitive = undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Number.isInteger(primitive)) {
|
||||
context.report({
|
||||
node: typeRef,
|
||||
messageId: 'primitiveOverridden',
|
||||
data: {
|
||||
literal: typeValues.map(name => name.typeName).join(' | '),
|
||||
primitive: primitiveTypeFlagNames[primitive],
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
if (seenUnionTypes.size > 0) {
|
||||
checkIfUnionsAreAssignable();
|
||||
return;
|
||||
}
|
||||
// For each primitive type of all the seen primitive types,
|
||||
// if there was a literal type seen that overrides it,
|
||||
// report each of the primitive type's type nodes
|
||||
for (const [primitiveTypeFlag, typeNodes] of seenPrimitiveTypes) {
|
||||
const matchedLiteralTypes = seenLiteralTypes.get(primitiveTypeFlag);
|
||||
if (matchedLiteralTypes) {
|
||||
for (const typeNode of typeNodes) {
|
||||
context.report({
|
||||
node: typeNode,
|
||||
messageId: 'primitiveOverridden',
|
||||
data: {
|
||||
literal: matchedLiteralTypes.join(' | '),
|
||||
primitive: primitiveTypeFlagNames[primitiveTypeFlag],
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'TSUnionType:exit'(node) {
|
||||
const seenLiteralTypes = new Map();
|
||||
const seenPrimitiveTypes = new Set();
|
||||
function checkUnionBottomAndTopTypes({ typeFlags, typeName }, typeNode) {
|
||||
for (const checkFlag of [
|
||||
ts.TypeFlags.Any,
|
||||
ts.TypeFlags.Unknown,
|
||||
]) {
|
||||
if (typeFlags === checkFlag) {
|
||||
context.report({
|
||||
node: typeNode,
|
||||
messageId: typeFlags === ts.TypeFlags.Any && typeName !== 'any'
|
||||
? 'errorTypeOverrides'
|
||||
: 'overrides',
|
||||
data: {
|
||||
container: 'union',
|
||||
typeName,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (typeFlags === ts.TypeFlags.Never &&
|
||||
!isNodeInsideReturnType(node)) {
|
||||
context.report({
|
||||
node: typeNode,
|
||||
messageId: 'overridden',
|
||||
data: {
|
||||
container: 'union',
|
||||
typeName: 'never',
|
||||
},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (const typeNode of node.types) {
|
||||
const typePartFlags = getTypeNodeTypePartFlagsCached(typeNode);
|
||||
for (const typePart of typePartFlags) {
|
||||
if (checkUnionBottomAndTopTypes(typePart, typeNode)) {
|
||||
continue;
|
||||
}
|
||||
for (const literalTypeFlag of literalTypeFlags) {
|
||||
if (typePart.typeFlags === literalTypeFlag) {
|
||||
addToMapGroup(seenLiteralTypes, literalToPrimitiveTypeFlags[literalTypeFlag], {
|
||||
literalValue: typePart.typeName,
|
||||
typeNode,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const primitiveTypeFlag of primitiveTypeFlags) {
|
||||
if ((typePart.typeFlags & primitiveTypeFlag) !== 0) {
|
||||
seenPrimitiveTypes.add(primitiveTypeFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const overriddenTypeNodes = new Map();
|
||||
// For each primitive type of all the seen literal types,
|
||||
// if there was a primitive type seen that overrides it,
|
||||
// upsert the literal text and primitive type under the backing type node
|
||||
for (const [primitiveTypeFlag, typeNodesWithText] of seenLiteralTypes) {
|
||||
if (seenPrimitiveTypes.has(primitiveTypeFlag)) {
|
||||
for (const { literalValue, typeNode } of typeNodesWithText) {
|
||||
addToMapGroup(overriddenTypeNodes, typeNode, {
|
||||
literalValue,
|
||||
primitiveTypeFlag,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// For each type node that had at least one overridden literal,
|
||||
// group those literals by their primitive type,
|
||||
// then report each primitive type with all its literals
|
||||
for (const [typeNode, typeFlagsWithText] of overriddenTypeNodes) {
|
||||
const grouped = (0, util_1.arrayGroupByToMap)(typeFlagsWithText, pair => pair.primitiveTypeFlag);
|
||||
for (const [primitiveTypeFlag, pairs] of grouped) {
|
||||
context.report({
|
||||
node: typeNode,
|
||||
messageId: 'literalOverridden',
|
||||
data: {
|
||||
literal: pairs.map(pair => pair.literalValue).join(' | '),
|
||||
primitive: primitiveTypeFlagNames[primitiveTypeFlag],
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -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,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2015.symbol" />
|
||||
/// <reference lib="decorators" />
|
||||
|
||||
interface SymbolConstructor {
|
||||
readonly metadata: unique symbol;
|
||||
}
|
||||
|
||||
interface Function {
|
||||
[Symbol.metadata]: DecoratorMetadata | null;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"moduleKind.enum.js","sourceRoot":"","sources":["../../src/enums/moduleKind.enum.ts"],"names":[],"mappings":"AAAA,sGAAsG;AAEtG,MAAM,CAAN,IAAY,UAeX;AAfD,WAAY,UAAU;IAClB,2CAAQ,CAAA;IACR,mDAAY,CAAA;IACZ,yCAAO,CAAA;IACP,yCAAO,CAAA;IACP,+CAAU,CAAA;IACV,+CAAU,CAAA;IACV,+CAAU,CAAA;IACV,+CAAU,CAAA;IACV,gDAAW,CAAA;IACX,iDAAY,CAAA;IACZ,iDAAY,CAAA;IACZ,iDAAY,CAAA;IACZ,qDAAc,CAAA;IACd,qDAAc,CAAA;AAClB,CAAC,EAfW,UAAU,KAAV,UAAU,QAerB"}
|
||||
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./astUtilities"), exports);
|
||||
__exportStar(require("./PatternMatcher"), exports);
|
||||
__exportStar(require("./predicates"), exports);
|
||||
__exportStar(require("./ReferenceTracker"), exports);
|
||||
__exportStar(require("./scopeAnalysis"), exports);
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Blake2b hash function. Focuses on 64-bit platforms, but in JS speed different from Blake2s is negligible.
|
||||
* @module
|
||||
* @deprecated
|
||||
*/
|
||||
import { BLAKE2b as B2B, blake2b as b2b } from './blake2.ts';
|
||||
/** @deprecated Use import from `noble/hashes/blake2` module */
|
||||
export const BLAKE2b: typeof B2B = B2B;
|
||||
/** @deprecated Use import from `noble/hashes/blake2` module */
|
||||
export const blake2b: typeof b2b = b2b;
|
||||
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
|
||||
var _regex = _interopRequireDefault(require("./regex.js"));
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function validate(uuid) {
|
||||
return typeof uuid === 'string' && _regex.default.test(uuid);
|
||||
}
|
||||
|
||||
var _default = validate;
|
||||
exports.default = _default;
|
||||
@@ -0,0 +1,23 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const { Writable } = require('stream')
|
||||
|
||||
function run (opts) {
|
||||
let data = ''
|
||||
return new Writable({
|
||||
autoDestroy: true,
|
||||
write (chunk, enc, cb) {
|
||||
data += chunk.toString()
|
||||
cb()
|
||||
},
|
||||
destroy (err, cb) {
|
||||
// process._rawDebug('destroy called')
|
||||
fs.writeFile(opts.dest, data, function (err2) {
|
||||
cb(err2 || err)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = run
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"internalSymbolName.js","sourceRoot":"","sources":["../../src/enums/internalSymbolName.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,MAAM,CAAC,IAAI,kBAAuB,CAAC;AACnC,CAAC,UAAU,kBAAkB;IACzB,kBAAkB,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC;IACtC,kBAAkB,CAAC,aAAa,CAAC,GAAG,eAAe,CAAC;IACpD,kBAAkB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;IACpC,kBAAkB,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;IACxC,kBAAkB,CAAC,YAAY,CAAC,GAAG,UAAU,CAAC;IAC9C,kBAAkB,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC;IAC1C,kBAAkB,CAAC,SAAS,CAAC,GAAG,WAAW,CAAC;IAC5C,kBAAkB,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC;IACtC,kBAAkB,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC;IAC1C,kBAAkB,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC;IACxD,kBAAkB,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;IACxC,kBAAkB,CAAC,UAAU,CAAC,GAAG,YAAY,CAAC;IAC9C,kBAAkB,CAAC,UAAU,CAAC,GAAG,YAAY,CAAC;IAC9C,kBAAkB,CAAC,uBAAuB,CAAC,GAAG,cAAc,CAAC;IAC7D,kBAAkB,CAAC,yBAAyB,CAAC,GAAG,2BAA2B,CAAC;IAC5E,kBAAkB,CAAC,kBAAkB,CAAC,GAAG,oBAAoB,CAAC;IAC9D,kBAAkB,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAC/C,kBAAkB,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAC1C,kBAAkB,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IACpC,kBAAkB,CAAC,eAAe,CAAC,GAAG,gBAAgB,CAAC;AAC3D,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC,CAAC"}
|
||||
@@ -0,0 +1,82 @@
|
||||
'use strict';
|
||||
|
||||
const _path = require('./shared/pathe.BSlhyZSM.cjs');
|
||||
|
||||
const pathSeparators = /* @__PURE__ */ new Set(["/", "\\", void 0]);
|
||||
const normalizedAliasSymbol = Symbol.for("pathe:normalizedAlias");
|
||||
const SLASH_RE = /[/\\]/;
|
||||
function normalizeAliases(_aliases) {
|
||||
if (_aliases[normalizedAliasSymbol]) {
|
||||
return _aliases;
|
||||
}
|
||||
const aliases = Object.fromEntries(
|
||||
Object.entries(_aliases).sort(([a], [b]) => _compareAliases(a, b))
|
||||
);
|
||||
for (const key in aliases) {
|
||||
for (const alias in aliases) {
|
||||
if (alias === key || key.startsWith(alias)) {
|
||||
continue;
|
||||
}
|
||||
if (aliases[key]?.startsWith(alias) && pathSeparators.has(aliases[key][alias.length])) {
|
||||
aliases[key] = aliases[alias] + aliases[key].slice(alias.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
Object.defineProperty(aliases, normalizedAliasSymbol, {
|
||||
value: true,
|
||||
enumerable: false
|
||||
});
|
||||
return aliases;
|
||||
}
|
||||
function resolveAlias(path, aliases) {
|
||||
const _path$1 = _path.normalizeWindowsPath(path);
|
||||
aliases = normalizeAliases(aliases);
|
||||
for (const [alias, to] of Object.entries(aliases)) {
|
||||
if (!_path$1.startsWith(alias)) {
|
||||
continue;
|
||||
}
|
||||
const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias;
|
||||
if (hasTrailingSlash(_path$1[_alias.length])) {
|
||||
return _path.join(to, _path$1.slice(alias.length));
|
||||
}
|
||||
}
|
||||
return _path$1;
|
||||
}
|
||||
function reverseResolveAlias(path, aliases) {
|
||||
const _path$1 = _path.normalizeWindowsPath(path);
|
||||
aliases = normalizeAliases(aliases);
|
||||
const matches = [];
|
||||
for (const [to, alias] of Object.entries(aliases)) {
|
||||
if (!_path$1.startsWith(alias)) {
|
||||
continue;
|
||||
}
|
||||
const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias;
|
||||
if (hasTrailingSlash(_path$1[_alias.length])) {
|
||||
matches.push(_path.join(to, _path$1.slice(alias.length)));
|
||||
}
|
||||
}
|
||||
return matches.sort((a, b) => b.length - a.length);
|
||||
}
|
||||
function filename(path) {
|
||||
const base = path.split(SLASH_RE).pop();
|
||||
if (!base) {
|
||||
return void 0;
|
||||
}
|
||||
const separatorIndex = base.lastIndexOf(".");
|
||||
if (separatorIndex <= 0) {
|
||||
return base;
|
||||
}
|
||||
return base.slice(0, separatorIndex);
|
||||
}
|
||||
function _compareAliases(a, b) {
|
||||
return b.split("/").length - a.split("/").length;
|
||||
}
|
||||
function hasTrailingSlash(path = "/") {
|
||||
const lastChar = path[path.length - 1];
|
||||
return lastChar === "/" || lastChar === "\\";
|
||||
}
|
||||
|
||||
exports.filename = filename;
|
||||
exports.normalizeAliases = normalizeAliases;
|
||||
exports.resolveAlias = resolveAlias;
|
||||
exports.reverseResolveAlias = reverseResolveAlias;
|
||||
@@ -0,0 +1,114 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert'
|
||||
import * as os from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
import * as url from 'node:url'
|
||||
|
||||
import { watchFileCreated } from '../helper'
|
||||
import pino from '../../'
|
||||
|
||||
const readFile = fs.promises.readFile
|
||||
|
||||
const { pid } = process
|
||||
const hostname = os.hostname()
|
||||
|
||||
// A subset of the test from core.test.js, we don't need all of them to check for compatibility
|
||||
function runTests (esVersion: string): void {
|
||||
test(`(ts -> ${esVersion}) pino.transport with file`, async (t) => {
|
||||
const destination = join(
|
||||
os.tmpdir(),
|
||||
'_' + Math.random().toString(36).substr(2, 9)
|
||||
)
|
||||
const transport = pino.transport({
|
||||
target: join(__dirname, '..', 'fixtures', 'ts', `to-file-transport.${esVersion}.cjs`),
|
||||
options: { destination }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination, { encoding: 'utf8' }))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test(`(ts -> ${esVersion}) pino.transport with file URL`, async (t) => {
|
||||
const destination = join(
|
||||
os.tmpdir(),
|
||||
'_' + Math.random().toString(36).substr(2, 9)
|
||||
)
|
||||
const transport = pino.transport({
|
||||
target: url.pathToFileURL(join(__dirname, '..', 'fixtures', 'ts', `to-file-transport.${esVersion}.cjs`)).href,
|
||||
options: { destination }
|
||||
})
|
||||
t.after(transport.end.bind(transport))
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
await watchFileCreated(destination)
|
||||
const result = JSON.parse(await readFile(destination, { encoding: 'utf8' }))
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
|
||||
test(`(ts -> ${esVersion}) pino.transport with two files`, async (t) => {
|
||||
const dest1 = join(
|
||||
os.tmpdir(),
|
||||
'_' + Math.random().toString(36).substr(2, 9)
|
||||
)
|
||||
const dest2 = join(
|
||||
os.tmpdir(),
|
||||
'_' + Math.random().toString(36).substr(2, 9)
|
||||
)
|
||||
const transport = pino.transport({
|
||||
targets: [{
|
||||
level: 'info',
|
||||
target: join(__dirname, '..', 'fixtures', 'ts', `to-file-transport.${esVersion}.cjs`),
|
||||
options: { destination: dest1 }
|
||||
}, {
|
||||
level: 'info',
|
||||
target: join(__dirname, '..', 'fixtures', 'ts', `to-file-transport.${esVersion}.cjs`),
|
||||
options: { destination: dest2 }
|
||||
}]
|
||||
})
|
||||
|
||||
t.after(transport.end.bind(transport))
|
||||
|
||||
const instance = pino(transport)
|
||||
instance.info('hello')
|
||||
|
||||
await Promise.all([watchFileCreated(dest1), watchFileCreated(dest2)])
|
||||
|
||||
const result1 = JSON.parse(await readFile(dest1, { encoding: 'utf8' }))
|
||||
delete result1.time
|
||||
assert.deepEqual(result1, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
const result2 = JSON.parse(await readFile(dest2, { encoding: 'utf8' }))
|
||||
delete result2.time
|
||||
assert.deepEqual(result2, {
|
||||
pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
runTests('es5')
|
||||
runTests('es6')
|
||||
runTests('es2017')
|
||||
runTests('esnext')
|
||||
@@ -0,0 +1,529 @@
|
||||
'use strict'
|
||||
|
||||
function deepClone (obj) {
|
||||
if (obj === null || typeof obj !== 'object') {
|
||||
return obj
|
||||
}
|
||||
|
||||
if (obj instanceof Date) {
|
||||
return new Date(obj.getTime())
|
||||
}
|
||||
|
||||
if (obj instanceof Array) {
|
||||
const cloned = []
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
cloned[i] = deepClone(obj[i])
|
||||
}
|
||||
return cloned
|
||||
}
|
||||
|
||||
if (typeof obj === 'object') {
|
||||
const cloned = Object.create(Object.getPrototypeOf(obj))
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
cloned[key] = deepClone(obj[key])
|
||||
}
|
||||
}
|
||||
return cloned
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
function parsePath (path) {
|
||||
const parts = []
|
||||
let current = ''
|
||||
let inBrackets = false
|
||||
let inQuotes = false
|
||||
let quoteChar = ''
|
||||
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
const char = path[i]
|
||||
|
||||
if (!inBrackets && char === '.') {
|
||||
if (current) {
|
||||
parts.push(current)
|
||||
current = ''
|
||||
}
|
||||
} else if (char === '[') {
|
||||
if (current) {
|
||||
parts.push(current)
|
||||
current = ''
|
||||
}
|
||||
inBrackets = true
|
||||
} else if (char === ']' && inBrackets) {
|
||||
// Always push the current value when closing brackets, even if it's an empty string
|
||||
parts.push(current)
|
||||
current = ''
|
||||
inBrackets = false
|
||||
inQuotes = false
|
||||
} else if ((char === '"' || char === "'") && inBrackets) {
|
||||
if (!inQuotes) {
|
||||
inQuotes = true
|
||||
quoteChar = char
|
||||
} else if (char === quoteChar) {
|
||||
inQuotes = false
|
||||
quoteChar = ''
|
||||
} else {
|
||||
current += char
|
||||
}
|
||||
} else {
|
||||
current += char
|
||||
}
|
||||
}
|
||||
|
||||
if (current) {
|
||||
parts.push(current)
|
||||
}
|
||||
|
||||
return parts
|
||||
}
|
||||
|
||||
function setValue (obj, parts, value) {
|
||||
let current = obj
|
||||
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
const key = parts[i]
|
||||
// Type safety: Check if current is an object before using 'in' operator
|
||||
if (typeof current !== 'object' || current === null || !(key in current)) {
|
||||
return false // Path doesn't exist, don't create it
|
||||
}
|
||||
if (typeof current[key] !== 'object' || current[key] === null) {
|
||||
return false // Path doesn't exist properly
|
||||
}
|
||||
current = current[key]
|
||||
}
|
||||
|
||||
const lastKey = parts[parts.length - 1]
|
||||
if (lastKey === '*') {
|
||||
if (Array.isArray(current)) {
|
||||
for (let i = 0; i < current.length; i++) {
|
||||
current[i] = value
|
||||
}
|
||||
} else if (typeof current === 'object' && current !== null) {
|
||||
for (const key in current) {
|
||||
if (Object.prototype.hasOwnProperty.call(current, key)) {
|
||||
current[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Type safety: Check if current is an object before using 'in' operator
|
||||
if (typeof current === 'object' && current !== null && lastKey in current && Object.prototype.hasOwnProperty.call(current, lastKey)) {
|
||||
current[lastKey] = value
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function removeKey (obj, parts) {
|
||||
let current = obj
|
||||
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
const key = parts[i]
|
||||
// Type safety: Check if current is an object before using 'in' operator
|
||||
if (typeof current !== 'object' || current === null || !(key in current)) {
|
||||
return false // Path doesn't exist, don't create it
|
||||
}
|
||||
if (typeof current[key] !== 'object' || current[key] === null) {
|
||||
return false // Path doesn't exist properly
|
||||
}
|
||||
current = current[key]
|
||||
}
|
||||
|
||||
const lastKey = parts[parts.length - 1]
|
||||
if (lastKey === '*') {
|
||||
if (Array.isArray(current)) {
|
||||
// For arrays, we can't really "remove" all items as that would change indices
|
||||
// Instead, we set them to undefined which will be omitted by JSON.stringify
|
||||
for (let i = 0; i < current.length; i++) {
|
||||
current[i] = undefined
|
||||
}
|
||||
} else if (typeof current === 'object' && current !== null) {
|
||||
for (const key in current) {
|
||||
if (Object.prototype.hasOwnProperty.call(current, key)) {
|
||||
delete current[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Type safety: Check if current is an object before using 'in' operator
|
||||
if (typeof current === 'object' && current !== null && lastKey in current && Object.prototype.hasOwnProperty.call(current, lastKey)) {
|
||||
delete current[lastKey]
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Sentinel object to distinguish between undefined value and non-existent path
|
||||
const PATH_NOT_FOUND = Symbol('PATH_NOT_FOUND')
|
||||
|
||||
function getValueIfExists (obj, parts) {
|
||||
let current = obj
|
||||
|
||||
for (const part of parts) {
|
||||
if (current === null || current === undefined) {
|
||||
return PATH_NOT_FOUND
|
||||
}
|
||||
// Type safety: Check if current is an object before property access
|
||||
if (typeof current !== 'object' || current === null) {
|
||||
return PATH_NOT_FOUND
|
||||
}
|
||||
// Check if the property exists before accessing it
|
||||
if (!(part in current)) {
|
||||
return PATH_NOT_FOUND
|
||||
}
|
||||
current = current[part]
|
||||
}
|
||||
|
||||
return current
|
||||
}
|
||||
|
||||
function getValue (obj, parts) {
|
||||
let current = obj
|
||||
|
||||
for (const part of parts) {
|
||||
if (current === null || current === undefined) {
|
||||
return undefined
|
||||
}
|
||||
// Type safety: Check if current is an object before property access
|
||||
if (typeof current !== 'object' || current === null) {
|
||||
return undefined
|
||||
}
|
||||
current = current[part]
|
||||
}
|
||||
|
||||
return current
|
||||
}
|
||||
|
||||
function redactPaths (obj, paths, censor, remove = false) {
|
||||
for (const path of paths) {
|
||||
const parts = parsePath(path)
|
||||
|
||||
if (parts.includes('*')) {
|
||||
redactWildcardPath(obj, parts, censor, path, remove)
|
||||
} else {
|
||||
if (remove) {
|
||||
removeKey(obj, parts)
|
||||
} else {
|
||||
// Get value only if path exists - single traversal
|
||||
const value = getValueIfExists(obj, parts)
|
||||
if (value === PATH_NOT_FOUND) {
|
||||
continue
|
||||
}
|
||||
|
||||
const actualCensor = typeof censor === 'function'
|
||||
? censor(value, parts)
|
||||
: censor
|
||||
setValue(obj, parts, actualCensor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function redactWildcardPath (obj, parts, censor, originalPath, remove = false) {
|
||||
const wildcardIndex = parts.indexOf('*')
|
||||
|
||||
if (wildcardIndex === parts.length - 1) {
|
||||
const parentParts = parts.slice(0, -1)
|
||||
let current = obj
|
||||
|
||||
for (const part of parentParts) {
|
||||
if (current === null || current === undefined) return
|
||||
// Type safety: Check if current is an object before property access
|
||||
if (typeof current !== 'object' || current === null) return
|
||||
current = current[part]
|
||||
}
|
||||
|
||||
if (Array.isArray(current)) {
|
||||
if (remove) {
|
||||
// For arrays, set all items to undefined which will be omitted by JSON.stringify
|
||||
for (let i = 0; i < current.length; i++) {
|
||||
current[i] = undefined
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < current.length; i++) {
|
||||
const indexPath = [...parentParts, i.toString()]
|
||||
const actualCensor = typeof censor === 'function'
|
||||
? censor(current[i], indexPath)
|
||||
: censor
|
||||
current[i] = actualCensor
|
||||
}
|
||||
}
|
||||
} else if (typeof current === 'object' && current !== null) {
|
||||
if (remove) {
|
||||
// Collect keys to delete to avoid issues with deleting during iteration
|
||||
const keysToDelete = []
|
||||
for (const key in current) {
|
||||
if (Object.prototype.hasOwnProperty.call(current, key)) {
|
||||
keysToDelete.push(key)
|
||||
}
|
||||
}
|
||||
for (const key of keysToDelete) {
|
||||
delete current[key]
|
||||
}
|
||||
} else {
|
||||
for (const key in current) {
|
||||
const keyPath = [...parentParts, key]
|
||||
const actualCensor = typeof censor === 'function'
|
||||
? censor(current[key], keyPath)
|
||||
: censor
|
||||
current[key] = actualCensor
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
redactIntermediateWildcard(obj, parts, censor, wildcardIndex, originalPath, remove)
|
||||
}
|
||||
}
|
||||
|
||||
function redactIntermediateWildcard (obj, parts, censor, wildcardIndex, originalPath, remove = false) {
|
||||
const beforeWildcard = parts.slice(0, wildcardIndex)
|
||||
const afterWildcard = parts.slice(wildcardIndex + 1)
|
||||
const pathArray = [] // Cached array to avoid allocations
|
||||
|
||||
function traverse (current, pathLength) {
|
||||
if (pathLength === beforeWildcard.length) {
|
||||
if (Array.isArray(current)) {
|
||||
for (let i = 0; i < current.length; i++) {
|
||||
pathArray[pathLength] = i.toString()
|
||||
traverse(current[i], pathLength + 1)
|
||||
}
|
||||
} else if (typeof current === 'object' && current !== null) {
|
||||
for (const key in current) {
|
||||
pathArray[pathLength] = key
|
||||
traverse(current[key], pathLength + 1)
|
||||
}
|
||||
}
|
||||
} else if (pathLength < beforeWildcard.length) {
|
||||
const nextKey = beforeWildcard[pathLength]
|
||||
// Type safety: Check if current is an object before using 'in' operator
|
||||
if (current && typeof current === 'object' && current !== null && nextKey in current) {
|
||||
pathArray[pathLength] = nextKey
|
||||
traverse(current[nextKey], pathLength + 1)
|
||||
}
|
||||
} else {
|
||||
// Check if afterWildcard contains more wildcards
|
||||
if (afterWildcard.includes('*')) {
|
||||
// Recursively handle remaining wildcards
|
||||
// Wrap censor to prepend current path context
|
||||
const wrappedCensor = typeof censor === 'function'
|
||||
? (value, path) => {
|
||||
const fullPath = [...pathArray.slice(0, pathLength), ...path]
|
||||
return censor(value, fullPath)
|
||||
}
|
||||
: censor
|
||||
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove)
|
||||
} else {
|
||||
// No more wildcards, apply the redaction directly
|
||||
if (remove) {
|
||||
removeKey(current, afterWildcard)
|
||||
} else {
|
||||
const actualCensor = typeof censor === 'function'
|
||||
? censor(getValue(current, afterWildcard), [...pathArray.slice(0, pathLength), ...afterWildcard])
|
||||
: censor
|
||||
setValue(current, afterWildcard, actualCensor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (beforeWildcard.length === 0) {
|
||||
traverse(obj, 0)
|
||||
} else {
|
||||
let current = obj
|
||||
for (let i = 0; i < beforeWildcard.length; i++) {
|
||||
const part = beforeWildcard[i]
|
||||
if (current === null || current === undefined) return
|
||||
// Type safety: Check if current is an object before property access
|
||||
if (typeof current !== 'object' || current === null) return
|
||||
current = current[part]
|
||||
pathArray[i] = part
|
||||
}
|
||||
if (current !== null && current !== undefined) {
|
||||
traverse(current, beforeWildcard.length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildPathStructure (pathsToClone) {
|
||||
if (pathsToClone.length === 0) {
|
||||
return null // No paths to redact
|
||||
}
|
||||
|
||||
// Parse all paths and organize by depth
|
||||
const pathStructure = new Map()
|
||||
for (const path of pathsToClone) {
|
||||
const parts = parsePath(path)
|
||||
let current = pathStructure
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const part = parts[i]
|
||||
if (!current.has(part)) {
|
||||
current.set(part, new Map())
|
||||
}
|
||||
current = current.get(part)
|
||||
}
|
||||
}
|
||||
return pathStructure
|
||||
}
|
||||
|
||||
function selectiveClone (obj, pathStructure) {
|
||||
if (!pathStructure) {
|
||||
return obj // No paths to redact, return original
|
||||
}
|
||||
|
||||
function cloneSelectively (source, pathMap, depth = 0) {
|
||||
if (!pathMap || pathMap.size === 0) {
|
||||
return source // No more paths to clone, return reference
|
||||
}
|
||||
|
||||
if (source === null || typeof source !== 'object') {
|
||||
return source
|
||||
}
|
||||
|
||||
if (source instanceof Date) {
|
||||
return new Date(source.getTime())
|
||||
}
|
||||
|
||||
if (Array.isArray(source)) {
|
||||
const cloned = []
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
const indexStr = i.toString()
|
||||
if (pathMap.has(indexStr) || pathMap.has('*')) {
|
||||
cloned[i] = cloneSelectively(source[i], pathMap.get(indexStr) || pathMap.get('*'))
|
||||
} else {
|
||||
cloned[i] = source[i] // Share reference for non-redacted items
|
||||
}
|
||||
}
|
||||
return cloned
|
||||
}
|
||||
|
||||
// Handle objects
|
||||
const cloned = Object.create(Object.getPrototypeOf(source))
|
||||
for (const key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
if (pathMap.has(key) || pathMap.has('*')) {
|
||||
cloned[key] = cloneSelectively(source[key], pathMap.get(key) || pathMap.get('*'))
|
||||
} else {
|
||||
cloned[key] = source[key] // Share reference for non-redacted properties
|
||||
}
|
||||
}
|
||||
}
|
||||
return cloned
|
||||
}
|
||||
|
||||
return cloneSelectively(obj, pathStructure)
|
||||
}
|
||||
|
||||
function validatePath (path) {
|
||||
if (typeof path !== 'string') {
|
||||
throw new Error('Paths must be (non-empty) strings')
|
||||
}
|
||||
|
||||
if (path === '') {
|
||||
throw new Error('Invalid redaction path ()')
|
||||
}
|
||||
|
||||
// Check for double dots
|
||||
if (path.includes('..')) {
|
||||
throw new Error(`Invalid redaction path (${path})`)
|
||||
}
|
||||
|
||||
// Check for comma-separated paths (invalid syntax)
|
||||
if (path.includes(',')) {
|
||||
throw new Error(`Invalid redaction path (${path})`)
|
||||
}
|
||||
|
||||
// Check for unmatched brackets
|
||||
let bracketCount = 0
|
||||
let inQuotes = false
|
||||
let quoteChar = ''
|
||||
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
const char = path[i]
|
||||
|
||||
if ((char === '"' || char === "'") && bracketCount > 0) {
|
||||
if (!inQuotes) {
|
||||
inQuotes = true
|
||||
quoteChar = char
|
||||
} else if (char === quoteChar) {
|
||||
inQuotes = false
|
||||
quoteChar = ''
|
||||
}
|
||||
} else if (char === '[' && !inQuotes) {
|
||||
bracketCount++
|
||||
} else if (char === ']' && !inQuotes) {
|
||||
bracketCount--
|
||||
if (bracketCount < 0) {
|
||||
throw new Error(`Invalid redaction path (${path})`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bracketCount !== 0) {
|
||||
throw new Error(`Invalid redaction path (${path})`)
|
||||
}
|
||||
}
|
||||
|
||||
function validatePaths (paths) {
|
||||
if (!Array.isArray(paths)) {
|
||||
throw new TypeError('paths must be an array')
|
||||
}
|
||||
|
||||
for (const path of paths) {
|
||||
validatePath(path)
|
||||
}
|
||||
}
|
||||
|
||||
function slowRedact (options = {}) {
|
||||
const {
|
||||
paths = [],
|
||||
censor = '[REDACTED]',
|
||||
serialize = JSON.stringify,
|
||||
strict = true,
|
||||
remove = false
|
||||
} = options
|
||||
|
||||
// Validate paths upfront to match fast-redact behavior
|
||||
validatePaths(paths)
|
||||
|
||||
// Build path structure once during setup, not on every call
|
||||
const pathStructure = buildPathStructure(paths)
|
||||
|
||||
return function redact (obj) {
|
||||
if (strict && (obj === null || typeof obj !== 'object')) {
|
||||
if (obj === null || obj === undefined) {
|
||||
return serialize ? serialize(obj) : obj
|
||||
}
|
||||
if (typeof obj !== 'object') {
|
||||
return serialize ? serialize(obj) : obj
|
||||
}
|
||||
}
|
||||
|
||||
// Only clone paths that need redaction
|
||||
const cloned = selectiveClone(obj, pathStructure)
|
||||
const original = obj // Keep reference to original for restore
|
||||
|
||||
let actualCensor = censor
|
||||
if (typeof censor === 'function') {
|
||||
actualCensor = censor
|
||||
}
|
||||
|
||||
redactPaths(cloned, paths, actualCensor, remove)
|
||||
|
||||
if (serialize === false) {
|
||||
cloned.restore = function () {
|
||||
return deepClone(original) // Full clone only when restore is called
|
||||
}
|
||||
return cloned
|
||||
}
|
||||
|
||||
if (typeof serialize === 'function') {
|
||||
return serialize(cloned)
|
||||
}
|
||||
|
||||
return JSON.stringify(cloned)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = slowRedact
|
||||
@@ -0,0 +1,2 @@
|
||||
export declare var ModuleResolutionKind: any;
|
||||
//# sourceMappingURL=moduleResolutionKind.d.ts.map
|
||||
@@ -0,0 +1,143 @@
|
||||
/*! *****************************************************************************
|
||||
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,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
declare namespace Intl {
|
||||
/**
|
||||
* An object with some or all properties of the `Intl.Segmenter` constructor `options` parameter.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/Segmenter#parameters)
|
||||
*/
|
||||
interface SegmenterOptions {
|
||||
/** The locale matching algorithm to use. For information about this option, see [Intl page](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_negotiation). */
|
||||
localeMatcher?: "best fit" | "lookup" | undefined;
|
||||
/** The type of input to be split */
|
||||
granularity?: "grapheme" | "word" | "sentence" | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Intl.Segmenter` object enables locale-sensitive text segmentation, enabling you to get meaningful items (graphemes, words or sentences) from a string.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter)
|
||||
*/
|
||||
interface Segmenter {
|
||||
/**
|
||||
* Returns `Segments` object containing the segments of the input string, using the segmenter's locale and granularity.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/segment)
|
||||
*
|
||||
* @param input - The text to be segmented as a `string`.
|
||||
*
|
||||
* @returns A new iterable Segments object containing the segments of the input string, using the segmenter's locale and granularity.
|
||||
*/
|
||||
segment(input: string): Segments;
|
||||
/**
|
||||
* The `resolvedOptions()` method of `Intl.Segmenter` instances returns a new object with properties reflecting the options computed during initialization of this `Segmenter` object.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/resolvedOptions)
|
||||
*/
|
||||
resolvedOptions(): ResolvedSegmenterOptions;
|
||||
}
|
||||
|
||||
interface ResolvedSegmenterOptions {
|
||||
locale: string;
|
||||
granularity: "grapheme" | "word" | "sentence";
|
||||
}
|
||||
|
||||
interface SegmentIterator<T> extends IteratorObject<T, BuiltinIteratorReturn, unknown> {
|
||||
[Symbol.iterator](): SegmentIterator<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Segments` object is an iterable collection of the segments of a text string. It is returned by a call to the `segment()` method of an `Intl.Segmenter` object.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/segment/Segments)
|
||||
*/
|
||||
interface Segments {
|
||||
/**
|
||||
* Returns an object describing the segment in the original string that includes the code unit at a specified index.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/segment/Segments/containing)
|
||||
*
|
||||
* @param codeUnitIndex - A number specifying the index of the code unit in the original input string. If the value is omitted, it defaults to `0`.
|
||||
*/
|
||||
containing(codeUnitIndex?: number): SegmentData | undefined;
|
||||
|
||||
/** Returns an iterator to iterate over the segments. */
|
||||
[Symbol.iterator](): SegmentIterator<SegmentData>;
|
||||
}
|
||||
|
||||
interface SegmentData {
|
||||
/** A string containing the segment extracted from the original input string. */
|
||||
segment: string;
|
||||
/** The code unit index in the original input string at which the segment begins. */
|
||||
index: number;
|
||||
/** The complete input string that was segmented. */
|
||||
input: string;
|
||||
/**
|
||||
* A boolean value only if granularity is "word"; otherwise, undefined.
|
||||
* If granularity is "word", then isWordLike is true when the segment is word-like (i.e., consists of letters/numbers/ideographs/etc.); otherwise, false.
|
||||
*/
|
||||
isWordLike?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Intl.Segmenter` object enables locale-sensitive text segmentation, enabling you to get meaningful items (graphemes, words or sentences) from a string.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter)
|
||||
*/
|
||||
const Segmenter: {
|
||||
prototype: Segmenter;
|
||||
|
||||
/**
|
||||
* Creates a new `Intl.Segmenter` object.
|
||||
*
|
||||
* @param locales - A string with a [BCP 47 language tag](http://tools.ietf.org/html/rfc5646), or an array of such strings.
|
||||
* For the general form and interpretation of the `locales` argument,
|
||||
* see the [`Intl` page](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation).
|
||||
*
|
||||
* @param options - An [object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/Segmenter#parameters)
|
||||
* with some or all options of `SegmenterOptions`.
|
||||
*
|
||||
* @returns [Intl.Segmenter](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segments) object.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter).
|
||||
*/
|
||||
new (locales?: LocalesArgument, options?: SegmenterOptions): Segmenter;
|
||||
|
||||
/**
|
||||
* Returns an array containing those of the provided locales that are supported without having to fall back to the runtime's default locale.
|
||||
*
|
||||
* @param locales - A string with a [BCP 47 language tag](http://tools.ietf.org/html/rfc5646), or an array of such strings.
|
||||
* For the general form and interpretation of the `locales` argument,
|
||||
* see the [`Intl` page](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation).
|
||||
*
|
||||
* @param options An [object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/supportedLocalesOf#parameters).
|
||||
* with some or all possible options.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/supportedLocalesOf)
|
||||
*/
|
||||
supportedLocalesOf(locales: LocalesArgument, options?: Pick<SegmenterOptions, "localeMatcher">): UnicodeBCP47LocaleIdentifier[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a sorted array of the supported collation, calendar, currency, numbering system, timezones, and units by the implementation.
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/supportedValuesOf)
|
||||
*
|
||||
* @param key A string indicating the category of values to return.
|
||||
* @returns A sorted array of the supported values.
|
||||
*/
|
||||
function supportedValuesOf(key: "calendar" | "collation" | "currency" | "numberingSystem" | "timeZone" | "unit"): string[];
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"completionItemKind.d.ts","sourceRoot":"","sources":["../../src/enums/completionItemKind.ts"],"names":[],"mappings":"AACA,eAAO,IAAI,kBAAkB,EAAE,GAAG,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_wrap_async_generator.cjs",
|
||||
"module": "../../esm/_wrap_async_generator.js"
|
||||
}
|
||||
@@ -0,0 +1,749 @@
|
||||
// ==================================================================================================
|
||||
// JSON Schema Draft 04
|
||||
// ==================================================================================================
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1
|
||||
*/
|
||||
export type JSONSchema4TypeName =
|
||||
| "string" //
|
||||
| "number"
|
||||
| "integer"
|
||||
| "boolean"
|
||||
| "object"
|
||||
| "array"
|
||||
| "null"
|
||||
| "any";
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5
|
||||
*/
|
||||
export type JSONSchema4Type =
|
||||
| string //
|
||||
| number
|
||||
| boolean
|
||||
| JSONSchema4Object
|
||||
| JSONSchema4Array
|
||||
| null;
|
||||
|
||||
// Workaround for infinite type recursion
|
||||
export interface JSONSchema4Object {
|
||||
[key: string]: JSONSchema4Type;
|
||||
}
|
||||
|
||||
// Workaround for infinite type recursion
|
||||
// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
|
||||
export interface JSONSchema4Array extends Array<JSONSchema4Type> {}
|
||||
|
||||
/**
|
||||
* Meta schema
|
||||
*
|
||||
* Recommended values:
|
||||
* - 'http://json-schema.org/schema#'
|
||||
* - 'http://json-schema.org/hyper-schema#'
|
||||
* - 'http://json-schema.org/draft-04/schema#'
|
||||
* - 'http://json-schema.org/draft-04/hyper-schema#'
|
||||
* - 'http://json-schema.org/draft-03/schema#'
|
||||
* - 'http://json-schema.org/draft-03/hyper-schema#'
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5
|
||||
*/
|
||||
export type JSONSchema4Version = string;
|
||||
|
||||
/**
|
||||
* JSON Schema V4
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-04
|
||||
*/
|
||||
export interface JSONSchema4 {
|
||||
id?: string | undefined;
|
||||
$ref?: string | undefined;
|
||||
$schema?: JSONSchema4Version | undefined;
|
||||
|
||||
/**
|
||||
* This attribute is a string that provides a short description of the
|
||||
* instance property.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21
|
||||
*/
|
||||
title?: string | undefined;
|
||||
|
||||
/**
|
||||
* This attribute is a string that provides a full description of the of
|
||||
* purpose the instance property.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22
|
||||
*/
|
||||
description?: string | undefined;
|
||||
|
||||
default?: JSONSchema4Type | undefined;
|
||||
multipleOf?: number | undefined;
|
||||
maximum?: number | undefined;
|
||||
exclusiveMaximum?: boolean | undefined;
|
||||
minimum?: number | undefined;
|
||||
exclusiveMinimum?: boolean | undefined;
|
||||
maxLength?: number | undefined;
|
||||
minLength?: number | undefined;
|
||||
pattern?: string | undefined;
|
||||
|
||||
/**
|
||||
* May only be defined when "items" is defined, and is a tuple of JSONSchemas.
|
||||
*
|
||||
* This provides a definition for additional items in an array instance
|
||||
* when tuple definitions of the items is provided. This can be false
|
||||
* to indicate additional items in the array are not allowed, or it can
|
||||
* be a schema that defines the schema of the additional items.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.6
|
||||
*/
|
||||
additionalItems?: boolean | JSONSchema4 | undefined;
|
||||
|
||||
/**
|
||||
* This attribute defines the allowed items in an instance array, and
|
||||
* MUST be a schema or an array of schemas. The default value is an
|
||||
* empty schema which allows any value for items in the instance array.
|
||||
*
|
||||
* When this attribute value is a schema and the instance value is an
|
||||
* array, then all the items in the array MUST be valid according to the
|
||||
* schema.
|
||||
*
|
||||
* When this attribute value is an array of schemas and the instance
|
||||
* value is an array, each position in the instance array MUST conform
|
||||
* to the schema in the corresponding position for this array. This
|
||||
* called tuple typing. When tuple typing is used, additional items are
|
||||
* allowed, disallowed, or constrained by the "additionalItems"
|
||||
* (Section 5.6) attribute using the same rules as
|
||||
* "additionalProperties" (Section 5.4) for objects.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.5
|
||||
*/
|
||||
items?: JSONSchema4 | JSONSchema4[] | undefined;
|
||||
|
||||
maxItems?: number | undefined;
|
||||
minItems?: number | undefined;
|
||||
uniqueItems?: boolean | undefined;
|
||||
maxProperties?: number | undefined;
|
||||
minProperties?: number | undefined;
|
||||
|
||||
/**
|
||||
* This attribute indicates if the instance must have a value, and not
|
||||
* be undefined. This is false by default, making the instance
|
||||
* optional.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7
|
||||
*/
|
||||
required?: boolean | string[] | undefined;
|
||||
|
||||
/**
|
||||
* This attribute defines a schema for all properties that are not
|
||||
* explicitly defined in an object type definition. If specified, the
|
||||
* value MUST be a schema or a boolean. If false is provided, no
|
||||
* additional properties are allowed beyond the properties defined in
|
||||
* the schema. The default value is an empty schema which allows any
|
||||
* value for additional properties.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4
|
||||
*/
|
||||
additionalProperties?: boolean | JSONSchema4 | undefined;
|
||||
|
||||
definitions?: {
|
||||
[k: string]: JSONSchema4;
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* This attribute is an object with property definitions that define the
|
||||
* valid values of instance object property values. When the instance
|
||||
* value is an object, the property values of the instance object MUST
|
||||
* conform to the property definitions in this object. In this object,
|
||||
* each property definition's value MUST be a schema, and the property's
|
||||
* name MUST be the name of the instance property that it defines. The
|
||||
* instance property value MUST be valid according to the schema from
|
||||
* the property definition. Properties are considered unordered, the
|
||||
* order of the instance properties MAY be in any order.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.2
|
||||
*/
|
||||
properties?: {
|
||||
[k: string]: JSONSchema4;
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* This attribute is an object that defines the schema for a set of
|
||||
* property names of an object instance. The name of each property of
|
||||
* this attribute's object is a regular expression pattern in the ECMA
|
||||
* 262/Perl 5 format, while the value is a schema. If the pattern
|
||||
* matches the name of a property on the instance object, the value of
|
||||
* the instance's property MUST be valid against the pattern name's
|
||||
* schema value.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.3
|
||||
*/
|
||||
patternProperties?: {
|
||||
[k: string]: JSONSchema4;
|
||||
} | undefined;
|
||||
dependencies?: {
|
||||
[k: string]: JSONSchema4 | string[];
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* This provides an enumeration of all possible values that are valid
|
||||
* for the instance property. This MUST be an array, and each item in
|
||||
* the array represents a possible value for the instance value. If
|
||||
* this attribute is defined, the instance value MUST be one of the
|
||||
* values in the array in order for the schema to be valid.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
|
||||
*/
|
||||
enum?: JSONSchema4Type[] | undefined;
|
||||
|
||||
/**
|
||||
* A single type, or a union of simple types
|
||||
*/
|
||||
type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined;
|
||||
|
||||
allOf?: JSONSchema4[] | undefined;
|
||||
anyOf?: JSONSchema4[] | undefined;
|
||||
oneOf?: JSONSchema4[] | undefined;
|
||||
not?: JSONSchema4 | undefined;
|
||||
|
||||
/**
|
||||
* The value of this property MUST be another schema which will provide
|
||||
* a base schema which the current schema will inherit from. The
|
||||
* inheritance rules are such that any instance that is valid according
|
||||
* to the current schema MUST be valid according to the referenced
|
||||
* schema. This MAY also be an array, in which case, the instance MUST
|
||||
* be valid for all the schemas in the array. A schema that extends
|
||||
* another schema MAY define additional attributes, constrain existing
|
||||
* attributes, or add other constraints.
|
||||
*
|
||||
* Conceptually, the behavior of extends can be seen as validating an
|
||||
* instance against all constraints in the extending schema as well as
|
||||
* the extended schema(s).
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.26
|
||||
*/
|
||||
extends?: string | string[] | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-5.6
|
||||
*/
|
||||
[k: string]: any;
|
||||
|
||||
format?: string | undefined;
|
||||
}
|
||||
|
||||
// ==================================================================================================
|
||||
// JSON Schema Draft 06
|
||||
// ==================================================================================================
|
||||
|
||||
export type JSONSchema6TypeName =
|
||||
| "string" //
|
||||
| "number"
|
||||
| "integer"
|
||||
| "boolean"
|
||||
| "object"
|
||||
| "array"
|
||||
| "null"
|
||||
| "any";
|
||||
|
||||
export type JSONSchema6Type =
|
||||
| string //
|
||||
| number
|
||||
| boolean
|
||||
| JSONSchema6Object
|
||||
| JSONSchema6Array
|
||||
| null;
|
||||
|
||||
// Workaround for infinite type recursion
|
||||
export interface JSONSchema6Object {
|
||||
[key: string]: JSONSchema6Type;
|
||||
}
|
||||
|
||||
// Workaround for infinite type recursion
|
||||
// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
|
||||
export interface JSONSchema6Array extends Array<JSONSchema6Type> {}
|
||||
|
||||
/**
|
||||
* Meta schema
|
||||
*
|
||||
* Recommended values:
|
||||
* - 'http://json-schema.org/schema#'
|
||||
* - 'http://json-schema.org/hyper-schema#'
|
||||
* - 'http://json-schema.org/draft-06/schema#'
|
||||
* - 'http://json-schema.org/draft-06/hyper-schema#'
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5
|
||||
*/
|
||||
export type JSONSchema6Version = string;
|
||||
|
||||
/**
|
||||
* JSON Schema V6
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01
|
||||
*/
|
||||
export type JSONSchema6Definition = JSONSchema6 | boolean;
|
||||
export interface JSONSchema6 {
|
||||
$id?: string | undefined;
|
||||
$ref?: string | undefined;
|
||||
$schema?: JSONSchema6Version | undefined;
|
||||
|
||||
/**
|
||||
* Must be strictly greater than 0.
|
||||
* A numeric instance is valid only if division by this keyword's value results in an integer.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.1
|
||||
*/
|
||||
multipleOf?: number | undefined;
|
||||
|
||||
/**
|
||||
* Representing an inclusive upper limit for a numeric instance.
|
||||
* This keyword validates only if the instance is less than or exactly equal to "maximum".
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.2
|
||||
*/
|
||||
maximum?: number | undefined;
|
||||
|
||||
/**
|
||||
* Representing an exclusive upper limit for a numeric instance.
|
||||
* This keyword validates only if the instance is strictly less than (not equal to) to "exclusiveMaximum".
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.3
|
||||
*/
|
||||
exclusiveMaximum?: number | undefined;
|
||||
|
||||
/**
|
||||
* Representing an inclusive lower limit for a numeric instance.
|
||||
* This keyword validates only if the instance is greater than or exactly equal to "minimum".
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.4
|
||||
*/
|
||||
minimum?: number | undefined;
|
||||
|
||||
/**
|
||||
* Representing an exclusive lower limit for a numeric instance.
|
||||
* This keyword validates only if the instance is strictly greater than (not equal to) to "exclusiveMinimum".
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.5
|
||||
*/
|
||||
exclusiveMinimum?: number | undefined;
|
||||
|
||||
/**
|
||||
* Must be a non-negative integer.
|
||||
* A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.6
|
||||
*/
|
||||
maxLength?: number | undefined;
|
||||
|
||||
/**
|
||||
* Must be a non-negative integer.
|
||||
* A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword.
|
||||
* Omitting this keyword has the same behavior as a value of 0.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.7
|
||||
*/
|
||||
minLength?: number | undefined;
|
||||
|
||||
/**
|
||||
* Should be a valid regular expression, according to the ECMA 262 regular expression dialect.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.8
|
||||
*/
|
||||
pattern?: string | undefined;
|
||||
|
||||
/**
|
||||
* This keyword determines how child instances validate for arrays, and does not directly validate the immediate instance itself.
|
||||
* Omitting this keyword has the same behavior as an empty schema.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.9
|
||||
*/
|
||||
items?: JSONSchema6Definition | JSONSchema6Definition[] | undefined;
|
||||
|
||||
/**
|
||||
* This keyword determines how child instances validate for arrays, and does not directly validate the immediate instance itself.
|
||||
* If "items" is an array of schemas, validation succeeds if every instance element
|
||||
* at a position greater than the size of "items" validates against "additionalItems".
|
||||
* Otherwise, "additionalItems" MUST be ignored, as the "items" schema
|
||||
* (possibly the default value of an empty schema) is applied to all elements.
|
||||
* Omitting this keyword has the same behavior as an empty schema.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.10
|
||||
*/
|
||||
additionalItems?: JSONSchema6Definition | undefined;
|
||||
|
||||
/**
|
||||
* Must be a non-negative integer.
|
||||
* An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.11
|
||||
*/
|
||||
maxItems?: number | undefined;
|
||||
|
||||
/**
|
||||
* Must be a non-negative integer.
|
||||
* An array instance is valid against "maxItems" if its size is greater than, or equal to, the value of this keyword.
|
||||
* Omitting this keyword has the same behavior as a value of 0.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.12
|
||||
*/
|
||||
minItems?: number | undefined;
|
||||
|
||||
/**
|
||||
* If this keyword has boolean value false, the instance validates successfully.
|
||||
* If it has boolean value true, the instance validates successfully if all of its elements are unique.
|
||||
* Omitting this keyword has the same behavior as a value of false.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.13
|
||||
*/
|
||||
uniqueItems?: boolean | undefined;
|
||||
|
||||
/**
|
||||
* An array instance is valid against "contains" if at least one of its elements is valid against the given schema.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.14
|
||||
*/
|
||||
contains?: JSONSchema6Definition | undefined;
|
||||
|
||||
/**
|
||||
* Must be a non-negative integer.
|
||||
* An object instance is valid against "maxProperties" if its number of properties is less than, or equal to, the value of this keyword.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.15
|
||||
*/
|
||||
maxProperties?: number | undefined;
|
||||
|
||||
/**
|
||||
* Must be a non-negative integer.
|
||||
* An object instance is valid against "maxProperties" if its number of properties is greater than,
|
||||
* or equal to, the value of this keyword.
|
||||
* Omitting this keyword has the same behavior as a value of 0.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.16
|
||||
*/
|
||||
minProperties?: number | undefined;
|
||||
|
||||
/**
|
||||
* Elements of this array must be unique.
|
||||
* An object instance is valid against this keyword if every item in the array is the name of a property in the instance.
|
||||
* Omitting this keyword has the same behavior as an empty array.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.17
|
||||
*/
|
||||
required?: string[] | undefined;
|
||||
|
||||
/**
|
||||
* This keyword determines how child instances validate for objects, and does not directly validate the immediate instance itself.
|
||||
* Validation succeeds if, for each name that appears in both the instance and as a name within this keyword's value,
|
||||
* the child instance for that name successfully validates against the corresponding schema.
|
||||
* Omitting this keyword has the same behavior as an empty object.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.18
|
||||
*/
|
||||
properties?: {
|
||||
[k: string]: JSONSchema6Definition;
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* This attribute is an object that defines the schema for a set of property names of an object instance.
|
||||
* The name of each property of this attribute's object is a regular expression pattern in the ECMA 262, while the value is a schema.
|
||||
* If the pattern matches the name of a property on the instance object, the value of the instance's property
|
||||
* MUST be valid against the pattern name's schema value.
|
||||
* Omitting this keyword has the same behavior as an empty object.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.19
|
||||
*/
|
||||
patternProperties?: {
|
||||
[k: string]: JSONSchema6Definition;
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* This attribute defines a schema for all properties that are not explicitly defined in an object type definition.
|
||||
* If specified, the value MUST be a schema or a boolean.
|
||||
* If false is provided, no additional properties are allowed beyond the properties defined in the schema.
|
||||
* The default value is an empty schema which allows any value for additional properties.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.20
|
||||
*/
|
||||
additionalProperties?: JSONSchema6Definition | undefined;
|
||||
|
||||
/**
|
||||
* This keyword specifies rules that are evaluated if the instance is an object and contains a certain property.
|
||||
* Each property specifies a dependency.
|
||||
* If the dependency value is an array, each element in the array must be unique.
|
||||
* Omitting this keyword has the same behavior as an empty object.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.21
|
||||
*/
|
||||
dependencies?: {
|
||||
[k: string]: JSONSchema6Definition | string[];
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* Takes a schema which validates the names of all properties rather than their values.
|
||||
* Note the property name that the schema is testing will always be a string.
|
||||
* Omitting this keyword has the same behavior as an empty schema.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.22
|
||||
*/
|
||||
propertyNames?: JSONSchema6Definition | undefined;
|
||||
|
||||
/**
|
||||
* This provides an enumeration of all possible values that are valid
|
||||
* for the instance property. This MUST be an array, and each item in
|
||||
* the array represents a possible value for the instance value. If
|
||||
* this attribute is defined, the instance value MUST be one of the
|
||||
* values in the array in order for the schema to be valid.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.23
|
||||
*/
|
||||
enum?: JSONSchema6Type[] | undefined;
|
||||
|
||||
/**
|
||||
* More readable form of a one-element "enum"
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.24
|
||||
*/
|
||||
const?: JSONSchema6Type | undefined;
|
||||
|
||||
/**
|
||||
* A single type, or a union of simple types
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.25
|
||||
*/
|
||||
type?: JSONSchema6TypeName | JSONSchema6TypeName[] | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.26
|
||||
*/
|
||||
allOf?: JSONSchema6Definition[] | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.27
|
||||
*/
|
||||
anyOf?: JSONSchema6Definition[] | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.28
|
||||
*/
|
||||
oneOf?: JSONSchema6Definition[] | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.29
|
||||
*/
|
||||
not?: JSONSchema6Definition | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-7.1
|
||||
*/
|
||||
definitions?: {
|
||||
[k: string]: JSONSchema6Definition;
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* This attribute is a string that provides a short description of the instance property.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-7.2
|
||||
*/
|
||||
title?: string | undefined;
|
||||
|
||||
/**
|
||||
* This attribute is a string that provides a full description of the of purpose the instance property.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-7.2
|
||||
*/
|
||||
description?: string | undefined;
|
||||
|
||||
/**
|
||||
* This keyword can be used to supply a default JSON value associated with a particular schema.
|
||||
* It is RECOMMENDED that a default value be valid against the associated schema.
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-7.3
|
||||
*/
|
||||
default?: JSONSchema6Type | undefined;
|
||||
|
||||
/**
|
||||
* Array of examples with no validation effect the value of "default" is usable as an example without repeating it under this keyword
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-7.4
|
||||
*/
|
||||
examples?: JSONSchema6Type[] | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-8
|
||||
*/
|
||||
format?: string | undefined;
|
||||
}
|
||||
|
||||
// ==================================================================================================
|
||||
// JSON Schema Draft 07
|
||||
// ==================================================================================================
|
||||
// https://tools.ietf.org/html/draft-handrews-json-schema-validation-01
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Primitive type
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1
|
||||
*/
|
||||
export type JSONSchema7TypeName =
|
||||
| "string" //
|
||||
| "number"
|
||||
| "integer"
|
||||
| "boolean"
|
||||
| "object"
|
||||
| "array"
|
||||
| "null";
|
||||
|
||||
/**
|
||||
* Primitive type
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1
|
||||
*/
|
||||
export type JSONSchema7Type =
|
||||
| string //
|
||||
| number
|
||||
| boolean
|
||||
| JSONSchema7Object
|
||||
| JSONSchema7Array
|
||||
| null;
|
||||
|
||||
// Workaround for infinite type recursion
|
||||
export interface JSONSchema7Object {
|
||||
[key: string]: JSONSchema7Type;
|
||||
}
|
||||
|
||||
// Workaround for infinite type recursion
|
||||
// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
|
||||
export interface JSONSchema7Array extends Array<JSONSchema7Type> {}
|
||||
|
||||
/**
|
||||
* Meta schema
|
||||
*
|
||||
* Recommended values:
|
||||
* - 'http://json-schema.org/schema#'
|
||||
* - 'http://json-schema.org/hyper-schema#'
|
||||
* - 'http://json-schema.org/draft-07/schema#'
|
||||
* - 'http://json-schema.org/draft-07/hyper-schema#'
|
||||
*
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5
|
||||
*/
|
||||
export type JSONSchema7Version = string;
|
||||
|
||||
/**
|
||||
* JSON Schema v7
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01
|
||||
*/
|
||||
export type JSONSchema7Definition = JSONSchema7 | boolean;
|
||||
export interface JSONSchema7 {
|
||||
$id?: string | undefined;
|
||||
$ref?: string | undefined;
|
||||
$schema?: JSONSchema7Version | undefined;
|
||||
$comment?: string | undefined;
|
||||
|
||||
/**
|
||||
* @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-8.2.4
|
||||
* @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#appendix-A
|
||||
*/
|
||||
$defs?: {
|
||||
[key: string]: JSONSchema7Definition;
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1
|
||||
*/
|
||||
type?: JSONSchema7TypeName | JSONSchema7TypeName[] | undefined;
|
||||
enum?: JSONSchema7Type[] | undefined;
|
||||
const?: JSONSchema7Type | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.2
|
||||
*/
|
||||
multipleOf?: number | undefined;
|
||||
maximum?: number | undefined;
|
||||
exclusiveMaximum?: number | undefined;
|
||||
minimum?: number | undefined;
|
||||
exclusiveMinimum?: number | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.3
|
||||
*/
|
||||
maxLength?: number | undefined;
|
||||
minLength?: number | undefined;
|
||||
pattern?: string | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.4
|
||||
*/
|
||||
items?: JSONSchema7Definition | JSONSchema7Definition[] | undefined;
|
||||
additionalItems?: JSONSchema7Definition | undefined;
|
||||
maxItems?: number | undefined;
|
||||
minItems?: number | undefined;
|
||||
uniqueItems?: boolean | undefined;
|
||||
contains?: JSONSchema7Definition | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.5
|
||||
*/
|
||||
maxProperties?: number | undefined;
|
||||
minProperties?: number | undefined;
|
||||
required?: string[] | undefined;
|
||||
properties?: {
|
||||
[key: string]: JSONSchema7Definition;
|
||||
} | undefined;
|
||||
patternProperties?: {
|
||||
[key: string]: JSONSchema7Definition;
|
||||
} | undefined;
|
||||
additionalProperties?: JSONSchema7Definition | undefined;
|
||||
dependencies?: {
|
||||
[key: string]: JSONSchema7Definition | string[];
|
||||
} | undefined;
|
||||
propertyNames?: JSONSchema7Definition | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.6
|
||||
*/
|
||||
if?: JSONSchema7Definition | undefined;
|
||||
then?: JSONSchema7Definition | undefined;
|
||||
else?: JSONSchema7Definition | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.7
|
||||
*/
|
||||
allOf?: JSONSchema7Definition[] | undefined;
|
||||
anyOf?: JSONSchema7Definition[] | undefined;
|
||||
oneOf?: JSONSchema7Definition[] | undefined;
|
||||
not?: JSONSchema7Definition | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-7
|
||||
*/
|
||||
format?: string | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-8
|
||||
*/
|
||||
contentMediaType?: string | undefined;
|
||||
contentEncoding?: string | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-9
|
||||
*/
|
||||
definitions?: {
|
||||
[key: string]: JSONSchema7Definition;
|
||||
} | undefined;
|
||||
|
||||
/**
|
||||
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-10
|
||||
*/
|
||||
title?: string | undefined;
|
||||
description?: string | undefined;
|
||||
default?: JSONSchema7Type | undefined;
|
||||
readOnly?: boolean | undefined;
|
||||
writeOnly?: boolean | undefined;
|
||||
examples?: JSONSchema7Type | undefined;
|
||||
}
|
||||
|
||||
export interface ValidationResult {
|
||||
valid: boolean;
|
||||
errors: ValidationError[];
|
||||
}
|
||||
|
||||
export interface ValidationError {
|
||||
property: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* To use the validator call JSONSchema.validate with an instance object and an optional schema object.
|
||||
* If a schema is provided, it will be used to validate. If the instance object refers to a schema (self-validating),
|
||||
* that schema will be used to validate and the schema parameter is not necessary (if both exist,
|
||||
* both validations will occur).
|
||||
*/
|
||||
export function validate(instance: {}, schema: JSONSchema4 | JSONSchema6 | JSONSchema7): ValidationResult;
|
||||
|
||||
/**
|
||||
* The checkPropertyChange method will check to see if an value can legally be in property with the given schema
|
||||
* This is slightly different than the validate method in that it will fail if the schema is readonly and it will
|
||||
* not check for self-validation, it is assumed that the passed in value is already internally valid.
|
||||
*/
|
||||
export function checkPropertyChange(
|
||||
value: any,
|
||||
schema: JSONSchema4 | JSONSchema6 | JSONSchema7,
|
||||
property: string,
|
||||
): ValidationResult;
|
||||
|
||||
/**
|
||||
* This checks to ensure that the result is valid and will throw an appropriate error message if it is not.
|
||||
*/
|
||||
export function mustBeValid(result: ValidationResult): void;
|
||||
@@ -0,0 +1,327 @@
|
||||
/**
|
||||
* @fileoverview enforce or disallow capitalization of the first letter of a comment
|
||||
* @author Kevin Partington
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN,
|
||||
WHITESPACE = /\s/gu,
|
||||
MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/u, // TODO: Combine w/ max-len pattern?
|
||||
LETTER_PATTERN = /\p{L}/u;
|
||||
|
||||
/*
|
||||
* Base schema body for defining the basic capitalization rule, ignorePattern,
|
||||
* and ignoreInlineComments values.
|
||||
* This can be used in a few different ways in the actual schema.
|
||||
*/
|
||||
const SCHEMA_BODY = {
|
||||
type: "object",
|
||||
properties: {
|
||||
ignorePattern: {
|
||||
type: "string",
|
||||
},
|
||||
ignoreInlineComments: {
|
||||
type: "boolean",
|
||||
},
|
||||
ignoreConsecutiveComments: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
};
|
||||
const DEFAULTS = {
|
||||
ignorePattern: "",
|
||||
ignoreInlineComments: false,
|
||||
ignoreConsecutiveComments: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* Get normalized options for either block or line comments from the given
|
||||
* user-provided options.
|
||||
* - If the user-provided options is just a string, returns a normalized
|
||||
* set of options using default values for all other options.
|
||||
* - If the user-provided options is an object, then a normalized option
|
||||
* set is returned. Options specified in overrides will take priority
|
||||
* over options specified in the main options object, which will in
|
||||
* turn take priority over the rule's defaults.
|
||||
* @param {Object|string} rawOptions The user-provided options.
|
||||
* @param {string} which Either "line" or "block".
|
||||
* @returns {Object} The normalized options.
|
||||
*/
|
||||
function getNormalizedOptions(rawOptions, which) {
|
||||
return Object.assign({}, DEFAULTS, rawOptions[which] || rawOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get normalized options for block and line comments.
|
||||
* @param {Object|string} rawOptions The user-provided options.
|
||||
* @returns {Object} An object with "Line" and "Block" keys and corresponding
|
||||
* normalized options objects.
|
||||
*/
|
||||
function getAllNormalizedOptions(rawOptions = {}) {
|
||||
return {
|
||||
Line: getNormalizedOptions(rawOptions, "line"),
|
||||
Block: getNormalizedOptions(rawOptions, "block"),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a regular expression for each ignorePattern defined in the rule
|
||||
* options.
|
||||
*
|
||||
* This is done in order to avoid invoking the RegExp constructor repeatedly.
|
||||
* @param {Object} normalizedOptions The normalized rule options.
|
||||
* @returns {void}
|
||||
*/
|
||||
function createRegExpForIgnorePatterns(normalizedOptions) {
|
||||
Object.keys(normalizedOptions).forEach(key => {
|
||||
const ignorePatternStr = normalizedOptions[key].ignorePattern;
|
||||
|
||||
if (ignorePatternStr) {
|
||||
const regExp = RegExp(`^\\s*(?:${ignorePatternStr})`, "u");
|
||||
|
||||
normalizedOptions[key].ignorePatternRegExp = regExp;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Enforce or disallow capitalization of the first letter of a comment",
|
||||
recommended: false,
|
||||
frozen: true,
|
||||
url: "https://eslint.org/docs/latest/rules/capitalized-comments",
|
||||
},
|
||||
|
||||
fixable: "code",
|
||||
|
||||
schema: [
|
||||
{ enum: ["always", "never"] },
|
||||
{
|
||||
oneOf: [
|
||||
SCHEMA_BODY,
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
line: SCHEMA_BODY,
|
||||
block: SCHEMA_BODY,
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
defaultOptions: ["always"],
|
||||
|
||||
messages: {
|
||||
unexpectedLowercaseComment:
|
||||
"Comments should not begin with a lowercase character.",
|
||||
unexpectedUppercaseComment:
|
||||
"Comments should not begin with an uppercase character.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const capitalize = context.options[0],
|
||||
normalizedOptions = getAllNormalizedOptions(context.options[1]),
|
||||
sourceCode = context.sourceCode;
|
||||
|
||||
createRegExpForIgnorePatterns(normalizedOptions);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helpers
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks whether a comment is an inline comment.
|
||||
*
|
||||
* For the purpose of this rule, a comment is inline if:
|
||||
* 1. The comment is preceded by a token on the same line; and
|
||||
* 2. The command is followed by a token on the same line.
|
||||
*
|
||||
* Note that the comment itself need not be single-line!
|
||||
*
|
||||
* Also, it follows from this definition that only block comments can
|
||||
* be considered as possibly inline. This is because line comments
|
||||
* would consume any following tokens on the same line as the comment.
|
||||
* @param {ASTNode} comment The comment node to check.
|
||||
* @returns {boolean} True if the comment is an inline comment, false
|
||||
* otherwise.
|
||||
*/
|
||||
function isInlineComment(comment) {
|
||||
const previousToken = sourceCode.getTokenBefore(comment, {
|
||||
includeComments: true,
|
||||
}),
|
||||
nextToken = sourceCode.getTokenAfter(comment, {
|
||||
includeComments: true,
|
||||
});
|
||||
|
||||
return Boolean(
|
||||
previousToken &&
|
||||
nextToken &&
|
||||
comment.loc.start.line === previousToken.loc.end.line &&
|
||||
comment.loc.end.line === nextToken.loc.start.line,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a comment follows another comment.
|
||||
* @param {ASTNode} comment The comment to check.
|
||||
* @returns {boolean} True if the comment follows a valid comment.
|
||||
*/
|
||||
function isConsecutiveComment(comment) {
|
||||
const previousTokenOrComment = sourceCode.getTokenBefore(comment, {
|
||||
includeComments: true,
|
||||
});
|
||||
|
||||
return Boolean(
|
||||
previousTokenOrComment &&
|
||||
["Block", "Line"].includes(previousTokenOrComment.type),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a comment to determine if it is valid for this rule.
|
||||
* @param {ASTNode} comment The comment node to process.
|
||||
* @param {Object} options The options for checking this comment.
|
||||
* @returns {boolean} True if the comment is valid, false otherwise.
|
||||
*/
|
||||
function isCommentValid(comment, options) {
|
||||
// 1. Check for default ignore pattern.
|
||||
if (DEFAULT_IGNORE_PATTERN.test(comment.value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. Check for custom ignore pattern.
|
||||
const commentWithoutAsterisks = comment.value.replace(/\*/gu, "");
|
||||
|
||||
if (
|
||||
options.ignorePatternRegExp &&
|
||||
options.ignorePatternRegExp.test(commentWithoutAsterisks)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. Check for inline comments.
|
||||
if (options.ignoreInlineComments && isInlineComment(comment)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4. Is this a consecutive comment (and are we tolerating those)?
|
||||
if (
|
||||
options.ignoreConsecutiveComments &&
|
||||
isConsecutiveComment(comment)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 5. Does the comment start with a possible URL?
|
||||
if (MAYBE_URL.test(commentWithoutAsterisks)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6. Is the initial word character a letter?
|
||||
const commentWordCharsOnly = commentWithoutAsterisks.replace(
|
||||
WHITESPACE,
|
||||
"",
|
||||
);
|
||||
|
||||
if (commentWordCharsOnly.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the first Unicode character (1 or 2 code units).
|
||||
const [firstWordChar] = commentWordCharsOnly;
|
||||
|
||||
if (!LETTER_PATTERN.test(firstWordChar)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 7. Check the case of the initial word character.
|
||||
const isUppercase =
|
||||
firstWordChar !== firstWordChar.toLocaleLowerCase(),
|
||||
isLowercase =
|
||||
firstWordChar !== firstWordChar.toLocaleUpperCase();
|
||||
|
||||
if (capitalize === "always" && isLowercase) {
|
||||
return false;
|
||||
}
|
||||
if (capitalize === "never" && isUppercase) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a comment to determine if it needs to be reported.
|
||||
* @param {ASTNode} comment The comment node to process.
|
||||
* @returns {void}
|
||||
*/
|
||||
function processComment(comment) {
|
||||
const options = normalizedOptions[comment.type],
|
||||
commentValid = isCommentValid(comment, options);
|
||||
|
||||
if (!commentValid) {
|
||||
const messageId =
|
||||
capitalize === "always"
|
||||
? "unexpectedLowercaseComment"
|
||||
: "unexpectedUppercaseComment";
|
||||
|
||||
context.report({
|
||||
node: null, // Intentionally using loc instead
|
||||
loc: comment.loc,
|
||||
messageId,
|
||||
fix(fixer) {
|
||||
const match = comment.value.match(LETTER_PATTERN);
|
||||
const char = match[0];
|
||||
|
||||
// Offset match.index by 2 to account for the first 2 characters that start the comment (// or /*)
|
||||
const charIndex = comment.range[0] + match.index + 2;
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
[charIndex, charIndex + char.length],
|
||||
capitalize === "always"
|
||||
? char.toLocaleUpperCase()
|
||||
: char.toLocaleLowerCase(),
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Public
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
Program() {
|
||||
const comments = sourceCode.getAllComments();
|
||||
|
||||
comments
|
||||
.filter(token => token.type !== "Shebang")
|
||||
.forEach(processComment);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_async_to_generator.js";
|
||||
@@ -0,0 +1,51 @@
|
||||
# ieee754 [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
|
||||
|
||||
[travis-image]: https://img.shields.io/travis/feross/ieee754/master.svg
|
||||
[travis-url]: https://travis-ci.org/feross/ieee754
|
||||
[npm-image]: https://img.shields.io/npm/v/ieee754.svg
|
||||
[npm-url]: https://npmjs.org/package/ieee754
|
||||
[downloads-image]: https://img.shields.io/npm/dm/ieee754.svg
|
||||
[downloads-url]: https://npmjs.org/package/ieee754
|
||||
[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
|
||||
[standard-url]: https://standardjs.com
|
||||
|
||||
[![saucelabs][saucelabs-image]][saucelabs-url]
|
||||
|
||||
[saucelabs-image]: https://saucelabs.com/browser-matrix/ieee754.svg
|
||||
[saucelabs-url]: https://saucelabs.com/u/ieee754
|
||||
|
||||
### Read/write IEEE754 floating point numbers from/to a Buffer or array-like object.
|
||||
|
||||
## install
|
||||
|
||||
```
|
||||
npm install ieee754
|
||||
```
|
||||
|
||||
## methods
|
||||
|
||||
`var ieee754 = require('ieee754')`
|
||||
|
||||
The `ieee754` object has the following functions:
|
||||
|
||||
```
|
||||
ieee754.read = function (buffer, offset, isLE, mLen, nBytes)
|
||||
ieee754.write = function (buffer, value, offset, isLE, mLen, nBytes)
|
||||
```
|
||||
|
||||
The arguments mean the following:
|
||||
|
||||
- buffer = the buffer
|
||||
- offset = offset into the buffer
|
||||
- value = value to set (only for `write`)
|
||||
- isLe = is little endian?
|
||||
- mLen = mantissa length
|
||||
- nBytes = number of bytes
|
||||
|
||||
## what is ieee754?
|
||||
|
||||
The IEEE Standard for Floating-Point Arithmetic (IEEE 754) is a technical standard for floating-point computation. [Read more](http://en.wikipedia.org/wiki/IEEE_floating_point).
|
||||
|
||||
## license
|
||||
|
||||
BSD 3 Clause. Copyright (c) 2008, Fair Oaks Labs, Inc.
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { MinimatchOptions } from './index.js';
|
||||
/**
|
||||
* Escape all magic characters in a glob pattern.
|
||||
*
|
||||
* If the {@link MinimatchOptions.windowsPathsNoEscape}
|
||||
* option is used, then characters are escaped by wrapping in `[]`, because
|
||||
* a magic character wrapped in a character class can only be satisfied by
|
||||
* that exact character. In this mode, `\` is _not_ escaped, because it is
|
||||
* not interpreted as a magic character, but instead as a path separator.
|
||||
*
|
||||
* If the {@link MinimatchOptions.magicalBraces} option is used,
|
||||
* then braces (`{` and `}`) will be escaped.
|
||||
*/
|
||||
export declare const escape: (s: string, { windowsPathsNoEscape, magicalBraces, }?: Pick<MinimatchOptions, "windowsPathsNoEscape" | "magicalBraces">) => string;
|
||||
//# sourceMappingURL=escape.d.ts.map
|
||||
@@ -0,0 +1,315 @@
|
||||
// @ts-ignore TS6133
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v3";
|
||||
|
||||
test("valid", () => {
|
||||
expect(
|
||||
z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.parse({ type: "a", a: "abc" })
|
||||
).toEqual({ type: "a", a: "abc" });
|
||||
});
|
||||
|
||||
test("valid - discriminator value of various primitive types", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("1"), val: z.literal(1) }),
|
||||
z.object({ type: z.literal(1), val: z.literal(2) }),
|
||||
z.object({ type: z.literal(BigInt(1)), val: z.literal(3) }),
|
||||
z.object({ type: z.literal("true"), val: z.literal(4) }),
|
||||
z.object({ type: z.literal(true), val: z.literal(5) }),
|
||||
z.object({ type: z.literal("null"), val: z.literal(6) }),
|
||||
z.object({ type: z.literal(null), val: z.literal(7) }),
|
||||
z.object({ type: z.literal("undefined"), val: z.literal(8) }),
|
||||
z.object({ type: z.literal(undefined), val: z.literal(9) }),
|
||||
z.object({ type: z.literal("transform"), val: z.literal(10) }),
|
||||
z.object({ type: z.literal("refine"), val: z.literal(11) }),
|
||||
z.object({ type: z.literal("superRefine"), val: z.literal(12) }),
|
||||
]);
|
||||
|
||||
expect(schema.parse({ type: "1", val: 1 })).toEqual({ type: "1", val: 1 });
|
||||
expect(schema.parse({ type: 1, val: 2 })).toEqual({ type: 1, val: 2 });
|
||||
expect(schema.parse({ type: BigInt(1), val: 3 })).toEqual({
|
||||
type: BigInt(1),
|
||||
val: 3,
|
||||
});
|
||||
expect(schema.parse({ type: "true", val: 4 })).toEqual({
|
||||
type: "true",
|
||||
val: 4,
|
||||
});
|
||||
expect(schema.parse({ type: true, val: 5 })).toEqual({
|
||||
type: true,
|
||||
val: 5,
|
||||
});
|
||||
expect(schema.parse({ type: "null", val: 6 })).toEqual({
|
||||
type: "null",
|
||||
val: 6,
|
||||
});
|
||||
expect(schema.parse({ type: null, val: 7 })).toEqual({
|
||||
type: null,
|
||||
val: 7,
|
||||
});
|
||||
expect(schema.parse({ type: "undefined", val: 8 })).toEqual({
|
||||
type: "undefined",
|
||||
val: 8,
|
||||
});
|
||||
expect(schema.parse({ type: undefined, val: 9 })).toEqual({
|
||||
type: undefined,
|
||||
val: 9,
|
||||
});
|
||||
});
|
||||
|
||||
test("invalid - null", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
]).parse(null);
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(JSON.parse(e.message)).toEqual([
|
||||
{
|
||||
code: z.ZodIssueCode.invalid_type,
|
||||
expected: z.ZodParsedType.object,
|
||||
message: "Expected object, received null",
|
||||
received: z.ZodParsedType.null,
|
||||
path: [],
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test("invalid discriminator value", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
]).parse({ type: "x", a: "abc" });
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(JSON.parse(e.message)).toEqual([
|
||||
{
|
||||
code: z.ZodIssueCode.invalid_union_discriminator,
|
||||
options: ["a", "b"],
|
||||
message: "Invalid discriminator value. Expected 'a' | 'b'",
|
||||
path: ["type"],
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test("valid discriminator value, invalid data", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
]).parse({ type: "a", b: "abc" });
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(JSON.parse(e.message)).toEqual([
|
||||
{
|
||||
code: z.ZodIssueCode.invalid_type,
|
||||
expected: z.ZodParsedType.string,
|
||||
message: "Required",
|
||||
path: ["a"],
|
||||
received: z.ZodParsedType.undefined,
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test("wrong schema - missing discriminator", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ b: z.string() }) as any,
|
||||
]);
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(e.message.includes("could not be extracted")).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
test("wrong schema - duplicate discriminator values", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("a"), b: z.string() }),
|
||||
]);
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(e.message.includes("has duplicate value")).toEqual(true);
|
||||
}
|
||||
});
|
||||
|
||||
test("async - valid", async () => {
|
||||
expect(
|
||||
await z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("a"),
|
||||
a: z
|
||||
.string()
|
||||
.refine(async () => true)
|
||||
.transform(async (val) => Number(val)),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("b"),
|
||||
b: z.string(),
|
||||
}),
|
||||
])
|
||||
.parseAsync({ type: "a", a: "1" })
|
||||
).toEqual({ type: "a", a: 1 });
|
||||
});
|
||||
|
||||
test("async - invalid", async () => {
|
||||
try {
|
||||
await z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("a"),
|
||||
a: z
|
||||
.string()
|
||||
.refine(async () => true)
|
||||
.transform(async (val) => val),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("b"),
|
||||
b: z.string(),
|
||||
}),
|
||||
])
|
||||
.parseAsync({ type: "a", a: 1 });
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(JSON.parse(e.message)).toEqual([
|
||||
{
|
||||
code: "invalid_type",
|
||||
expected: "string",
|
||||
received: "number",
|
||||
path: ["a"],
|
||||
message: "Expected string, received number",
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test("valid - literals with .default or .preprocess", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("foo").default("foo"),
|
||||
a: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("custom"),
|
||||
method: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.preprocess((val) => String(val), z.literal("bar")),
|
||||
c: z.string(),
|
||||
}),
|
||||
]);
|
||||
expect(schema.parse({ type: "foo", a: "foo" })).toEqual({
|
||||
type: "foo",
|
||||
a: "foo",
|
||||
});
|
||||
});
|
||||
|
||||
test("enum and nativeEnum", () => {
|
||||
enum MyEnum {
|
||||
d = 0,
|
||||
e = "e",
|
||||
}
|
||||
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a"),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.enum(["b", "c"]),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.nativeEnum(MyEnum),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
// type schema = z.infer<typeof schema>;
|
||||
|
||||
schema.parse({ key: "a" });
|
||||
schema.parse({ key: "b" });
|
||||
schema.parse({ key: "c" });
|
||||
schema.parse({ key: MyEnum.d });
|
||||
schema.parse({ key: MyEnum.e });
|
||||
schema.parse({ key: "e" });
|
||||
});
|
||||
|
||||
test("branded", () => {
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a"),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.literal("b").brand("asdfaf"),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
// type schema = z.infer<typeof schema>;
|
||||
|
||||
schema.parse({ key: "a" });
|
||||
schema.parse({ key: "b" });
|
||||
expect(() => {
|
||||
schema.parse({ key: "c" });
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("optional and nullable", () => {
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a").optional(),
|
||||
a: z.literal(true),
|
||||
}),
|
||||
z.object({
|
||||
key: z.literal("b").nullable(),
|
||||
b: z.literal(true),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
type schema = z.infer<typeof schema>;
|
||||
z.util.assertEqual<schema, { key?: "a" | undefined; a: true } | { key: "b" | null; b: true }>(true);
|
||||
|
||||
schema.parse({ key: "a", a: true });
|
||||
schema.parse({ key: undefined, a: true });
|
||||
schema.parse({ key: "b", b: true });
|
||||
schema.parse({ key: null, b: true });
|
||||
expect(() => {
|
||||
schema.parse({ key: null, a: true });
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
schema.parse({ key: "b", a: true });
|
||||
}).toThrow();
|
||||
|
||||
const value = schema.parse({ key: null, b: true });
|
||||
|
||||
if (!("key" in value)) value.a;
|
||||
if (value.key === undefined) value.a;
|
||||
if (value.key === "a") value.a;
|
||||
if (value.key === "b") value.b;
|
||||
if (value.key === null) value.b;
|
||||
});
|
||||
|
||||
test("readonly array of options", () => {
|
||||
const options = [
|
||||
z.object({ type: z.literal("x"), val: z.literal(1) }),
|
||||
z.object({ type: z.literal("y"), val: z.literal(2) }),
|
||||
] as const;
|
||||
|
||||
expect(z.discriminatedUnion("type", options).parse({ type: "x", val: 1 })).toEqual({ type: "x", val: 1 });
|
||||
});
|
||||
@@ -0,0 +1,537 @@
|
||||
declare module "node:dgram" {
|
||||
import { NonSharedBuffer } from "node:buffer";
|
||||
import * as dns from "node:dns";
|
||||
import { Abortable, EventEmitter, InternalEventEmitter } from "node:events";
|
||||
import { AddressInfo, BlockList } from "node:net";
|
||||
interface RemoteInfo {
|
||||
address: string;
|
||||
family: "IPv4" | "IPv6";
|
||||
port: number;
|
||||
size: number;
|
||||
}
|
||||
interface BindOptions {
|
||||
port?: number | undefined;
|
||||
address?: string | undefined;
|
||||
exclusive?: boolean | undefined;
|
||||
fd?: number | undefined;
|
||||
}
|
||||
type SocketType = "udp4" | "udp6";
|
||||
interface SocketOptions extends Abortable {
|
||||
type: SocketType;
|
||||
reuseAddr?: boolean | undefined;
|
||||
reusePort?: boolean | undefined;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ipv6Only?: boolean | undefined;
|
||||
recvBufferSize?: number | undefined;
|
||||
sendBufferSize?: number | undefined;
|
||||
lookup?:
|
||||
| ((
|
||||
hostname: string,
|
||||
options: dns.LookupOneOptions,
|
||||
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
|
||||
) => void)
|
||||
| undefined;
|
||||
receiveBlockList?: BlockList | undefined;
|
||||
sendBlockList?: BlockList | undefined;
|
||||
}
|
||||
/**
|
||||
* Creates a `dgram.Socket` object. Once the socket is created, calling `socket.bind()` will instruct the socket to begin listening for datagram
|
||||
* messages. When `address` and `port` are not passed to `socket.bind()` the
|
||||
* method will bind the socket to the "all interfaces" address on a random port
|
||||
* (it does the right thing for both `udp4` and `udp6` sockets). The bound address
|
||||
* and port can be retrieved using `socket.address().address` and `socket.address().port`.
|
||||
*
|
||||
* If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.close()` on the socket:
|
||||
*
|
||||
* ```js
|
||||
* const controller = new AbortController();
|
||||
* const { signal } = controller;
|
||||
* const server = dgram.createSocket({ type: 'udp4', signal });
|
||||
* server.on('message', (msg, rinfo) => {
|
||||
* console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
|
||||
* });
|
||||
* // Later, when you want to close the server.
|
||||
* controller.abort();
|
||||
* ```
|
||||
* @since v0.11.13
|
||||
* @param options Available options are:
|
||||
* @param callback Attached as a listener for `'message'` events. Optional.
|
||||
*/
|
||||
function createSocket(type: SocketType, callback?: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): Socket;
|
||||
function createSocket(options: SocketOptions, callback?: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): Socket;
|
||||
interface SocketEventMap {
|
||||
"close": [];
|
||||
"connect": [];
|
||||
"error": [err: Error];
|
||||
"listening": [];
|
||||
"message": [msg: NonSharedBuffer, rinfo: RemoteInfo];
|
||||
}
|
||||
/**
|
||||
* Encapsulates the datagram functionality.
|
||||
*
|
||||
* New instances of `dgram.Socket` are created using {@link createSocket}.
|
||||
* The `new` keyword is not to be used to create `dgram.Socket` instances.
|
||||
* @since v0.1.99
|
||||
*/
|
||||
class Socket implements EventEmitter {
|
||||
/**
|
||||
* Tells the kernel to join a multicast group at the given `multicastAddress` and `multicastInterface` using the `IP_ADD_MEMBERSHIP` socket option. If the `multicastInterface` argument is not
|
||||
* specified, the operating system will choose
|
||||
* one interface and will add membership to it. To add membership to every
|
||||
* available interface, call `addMembership` multiple times, once per interface.
|
||||
*
|
||||
* When called on an unbound socket, this method will implicitly bind to a random
|
||||
* port, listening on all interfaces.
|
||||
*
|
||||
* When sharing a UDP socket across multiple `cluster` workers, the`socket.addMembership()` function must be called only once or an`EADDRINUSE` error will occur:
|
||||
*
|
||||
* ```js
|
||||
* import cluster from 'node:cluster';
|
||||
* import dgram from 'node:dgram';
|
||||
*
|
||||
* if (cluster.isPrimary) {
|
||||
* cluster.fork(); // Works ok.
|
||||
* cluster.fork(); // Fails with EADDRINUSE.
|
||||
* } else {
|
||||
* const s = dgram.createSocket('udp4');
|
||||
* s.bind(1234, () => {
|
||||
* s.addMembership('224.0.0.114');
|
||||
* });
|
||||
* }
|
||||
* ```
|
||||
* @since v0.6.9
|
||||
*/
|
||||
addMembership(multicastAddress: string, multicastInterface?: string): void;
|
||||
/**
|
||||
* Returns an object containing the address information for a socket.
|
||||
* For UDP sockets, this object will contain `address`, `family`, and `port` properties.
|
||||
*
|
||||
* This method throws `EBADF` if called on an unbound socket.
|
||||
* @since v0.1.99
|
||||
*/
|
||||
address(): AddressInfo;
|
||||
/**
|
||||
* For UDP sockets, causes the `dgram.Socket` to listen for datagram
|
||||
* messages on a named `port` and optional `address`. If `port` is not
|
||||
* specified or is `0`, the operating system will attempt to bind to a
|
||||
* random port. If `address` is not specified, the operating system will
|
||||
* attempt to listen on all addresses. Once binding is complete, a `'listening'` event is emitted and the optional `callback` function is
|
||||
* called.
|
||||
*
|
||||
* Specifying both a `'listening'` event listener and passing a `callback` to the `socket.bind()` method is not harmful but not very
|
||||
* useful.
|
||||
*
|
||||
* A bound datagram socket keeps the Node.js process running to receive
|
||||
* datagram messages.
|
||||
*
|
||||
* If binding fails, an `'error'` event is generated. In rare case (e.g.
|
||||
* attempting to bind with a closed socket), an `Error` may be thrown.
|
||||
*
|
||||
* Example of a UDP server listening on port 41234:
|
||||
*
|
||||
* ```js
|
||||
* import dgram from 'node:dgram';
|
||||
*
|
||||
* const server = dgram.createSocket('udp4');
|
||||
*
|
||||
* server.on('error', (err) => {
|
||||
* console.error(`server error:\n${err.stack}`);
|
||||
* server.close();
|
||||
* });
|
||||
*
|
||||
* server.on('message', (msg, rinfo) => {
|
||||
* console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
|
||||
* });
|
||||
*
|
||||
* server.on('listening', () => {
|
||||
* const address = server.address();
|
||||
* console.log(`server listening ${address.address}:${address.port}`);
|
||||
* });
|
||||
*
|
||||
* server.bind(41234);
|
||||
* // Prints: server listening 0.0.0.0:41234
|
||||
* ```
|
||||
* @since v0.1.99
|
||||
* @param callback with no parameters. Called when binding is complete.
|
||||
*/
|
||||
bind(port?: number, address?: string, callback?: () => void): this;
|
||||
bind(port?: number, callback?: () => void): this;
|
||||
bind(callback?: () => void): this;
|
||||
bind(options: BindOptions, callback?: () => void): this;
|
||||
/**
|
||||
* Close the underlying socket and stop listening for data on it. If a callback is
|
||||
* provided, it is added as a listener for the `'close'` event.
|
||||
* @since v0.1.99
|
||||
* @param callback Called when the socket has been closed.
|
||||
*/
|
||||
close(callback?: () => void): this;
|
||||
/**
|
||||
* Associates the `dgram.Socket` to a remote address and port. Every
|
||||
* message sent by this handle is automatically sent to that destination. Also,
|
||||
* the socket will only receive messages from that remote peer.
|
||||
* Trying to call `connect()` on an already connected socket will result
|
||||
* in an `ERR_SOCKET_DGRAM_IS_CONNECTED` exception. If `address` is not
|
||||
* provided, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets)
|
||||
* will be used by default. Once the connection is complete, a `'connect'` event
|
||||
* is emitted and the optional `callback` function is called. In case of failure,
|
||||
* the `callback` is called or, failing this, an `'error'` event is emitted.
|
||||
* @since v12.0.0
|
||||
* @param callback Called when the connection is completed or on error.
|
||||
*/
|
||||
connect(port: number, address?: string, callback?: () => void): void;
|
||||
connect(port: number, callback: () => void): void;
|
||||
/**
|
||||
* A synchronous function that disassociates a connected `dgram.Socket` from
|
||||
* its remote address. Trying to call `disconnect()` on an unbound or already
|
||||
* disconnected socket will result in an `ERR_SOCKET_DGRAM_NOT_CONNECTED` exception.
|
||||
* @since v12.0.0
|
||||
*/
|
||||
disconnect(): void;
|
||||
/**
|
||||
* Instructs the kernel to leave a multicast group at `multicastAddress` using the `IP_DROP_MEMBERSHIP` socket option. This method is automatically called by the
|
||||
* kernel when the socket is closed or the process terminates, so most apps will
|
||||
* never have reason to call this.
|
||||
*
|
||||
* If `multicastInterface` is not specified, the operating system will attempt to
|
||||
* drop membership on all valid interfaces.
|
||||
* @since v0.6.9
|
||||
*/
|
||||
dropMembership(multicastAddress: string, multicastInterface?: string): void;
|
||||
/**
|
||||
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||
* @since v8.7.0
|
||||
* @return the `SO_RCVBUF` socket receive buffer size in bytes.
|
||||
*/
|
||||
getRecvBufferSize(): number;
|
||||
/**
|
||||
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||
* @since v8.7.0
|
||||
* @return the `SO_SNDBUF` socket send buffer size in bytes.
|
||||
*/
|
||||
getSendBufferSize(): number;
|
||||
/**
|
||||
* @since v18.8.0, v16.19.0
|
||||
* @return Number of bytes queued for sending.
|
||||
*/
|
||||
getSendQueueSize(): number;
|
||||
/**
|
||||
* @since v18.8.0, v16.19.0
|
||||
* @return Number of send requests currently in the queue awaiting to be processed.
|
||||
*/
|
||||
getSendQueueCount(): number;
|
||||
/**
|
||||
* By default, binding a socket will cause it to block the Node.js process from
|
||||
* exiting as long as the socket is open. The `socket.unref()` method can be used
|
||||
* to exclude the socket from the reference counting that keeps the Node.js
|
||||
* process active. The `socket.ref()` method adds the socket back to the reference
|
||||
* counting and restores the default behavior.
|
||||
*
|
||||
* Calling `socket.ref()` multiples times will have no additional effect.
|
||||
*
|
||||
* The `socket.ref()` method returns a reference to the socket so calls can be
|
||||
* chained.
|
||||
* @since v0.9.1
|
||||
*/
|
||||
ref(): this;
|
||||
/**
|
||||
* Returns an object containing the `address`, `family`, and `port` of the remote
|
||||
* endpoint. This method throws an `ERR_SOCKET_DGRAM_NOT_CONNECTED` exception
|
||||
* if the socket is not connected.
|
||||
* @since v12.0.0
|
||||
*/
|
||||
remoteAddress(): AddressInfo;
|
||||
/**
|
||||
* Broadcasts a datagram on the socket.
|
||||
* For connectionless sockets, the destination `port` and `address` must be
|
||||
* specified. Connected sockets, on the other hand, will use their associated
|
||||
* remote endpoint, so the `port` and `address` arguments must not be set.
|
||||
*
|
||||
* The `msg` argument contains the message to be sent.
|
||||
* Depending on its type, different behavior can apply. If `msg` is a `Buffer`,
|
||||
* any `TypedArray` or a `DataView`,
|
||||
* the `offset` and `length` specify the offset within the `Buffer` where the
|
||||
* message begins and the number of bytes in the message, respectively.
|
||||
* If `msg` is a `String`, then it is automatically converted to a `Buffer` with `'utf8'` encoding. With messages that
|
||||
* contain multi-byte characters, `offset` and `length` will be calculated with
|
||||
* respect to `byte length` and not the character position.
|
||||
* If `msg` is an array, `offset` and `length` must not be specified.
|
||||
*
|
||||
* The `address` argument is a string. If the value of `address` is a host name,
|
||||
* DNS will be used to resolve the address of the host. If `address` is not
|
||||
* provided or otherwise nullish, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets) will be used by default.
|
||||
*
|
||||
* If the socket has not been previously bound with a call to `bind`, the socket
|
||||
* is assigned a random port number and is bound to the "all interfaces" address
|
||||
* (`'0.0.0.0'` for `udp4` sockets, `'::0'` for `udp6` sockets.)
|
||||
*
|
||||
* An optional `callback` function may be specified to as a way of reporting
|
||||
* DNS errors or for determining when it is safe to reuse the `buf` object.
|
||||
* DNS lookups delay the time to send for at least one tick of the
|
||||
* Node.js event loop.
|
||||
*
|
||||
* The only way to know for sure that the datagram has been sent is by using a `callback`. If an error occurs and a `callback` is given, the error will be
|
||||
* passed as the first argument to the `callback`. If a `callback` is not given,
|
||||
* the error is emitted as an `'error'` event on the `socket` object.
|
||||
*
|
||||
* Offset and length are optional but both _must_ be set if either are used.
|
||||
* They are supported only when the first argument is a `Buffer`, a `TypedArray`,
|
||||
* or a `DataView`.
|
||||
*
|
||||
* This method throws `ERR_SOCKET_BAD_PORT` if called on an unbound socket.
|
||||
*
|
||||
* Example of sending a UDP packet to a port on `localhost`;
|
||||
*
|
||||
* ```js
|
||||
* import dgram from 'node:dgram';
|
||||
* import { Buffer } from 'node:buffer';
|
||||
*
|
||||
* const message = Buffer.from('Some bytes');
|
||||
* const client = dgram.createSocket('udp4');
|
||||
* client.send(message, 41234, 'localhost', (err) => {
|
||||
* client.close();
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Example of sending a UDP packet composed of multiple buffers to a port on`127.0.0.1`;
|
||||
*
|
||||
* ```js
|
||||
* import dgram from 'node:dgram';
|
||||
* import { Buffer } from 'node:buffer';
|
||||
*
|
||||
* const buf1 = Buffer.from('Some ');
|
||||
* const buf2 = Buffer.from('bytes');
|
||||
* const client = dgram.createSocket('udp4');
|
||||
* client.send([buf1, buf2], 41234, (err) => {
|
||||
* client.close();
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Sending multiple buffers might be faster or slower depending on the
|
||||
* application and operating system. Run benchmarks to
|
||||
* determine the optimal strategy on a case-by-case basis. Generally speaking,
|
||||
* however, sending multiple buffers is faster.
|
||||
*
|
||||
* Example of sending a UDP packet using a socket connected to a port on `localhost`:
|
||||
*
|
||||
* ```js
|
||||
* import dgram from 'node:dgram';
|
||||
* import { Buffer } from 'node:buffer';
|
||||
*
|
||||
* const message = Buffer.from('Some bytes');
|
||||
* const client = dgram.createSocket('udp4');
|
||||
* client.connect(41234, 'localhost', (err) => {
|
||||
* client.send(message, (err) => {
|
||||
* client.close();
|
||||
* });
|
||||
* });
|
||||
* ```
|
||||
* @since v0.1.99
|
||||
* @param msg Message to be sent.
|
||||
* @param offset Offset in the buffer where the message starts.
|
||||
* @param length Number of bytes in the message.
|
||||
* @param port Destination port.
|
||||
* @param address Destination host name or IP address.
|
||||
* @param callback Called when the message has been sent.
|
||||
*/
|
||||
send(
|
||||
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||
port?: number,
|
||||
address?: string,
|
||||
callback?: (error: Error | null, bytes: number) => void,
|
||||
): void;
|
||||
send(
|
||||
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||
port?: number,
|
||||
callback?: (error: Error | null, bytes: number) => void,
|
||||
): void;
|
||||
send(
|
||||
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||
callback?: (error: Error | null, bytes: number) => void,
|
||||
): void;
|
||||
send(
|
||||
msg: string | NodeJS.ArrayBufferView,
|
||||
offset: number,
|
||||
length: number,
|
||||
port?: number,
|
||||
address?: string,
|
||||
callback?: (error: Error | null, bytes: number) => void,
|
||||
): void;
|
||||
send(
|
||||
msg: string | NodeJS.ArrayBufferView,
|
||||
offset: number,
|
||||
length: number,
|
||||
port?: number,
|
||||
callback?: (error: Error | null, bytes: number) => void,
|
||||
): void;
|
||||
send(
|
||||
msg: string | NodeJS.ArrayBufferView,
|
||||
offset: number,
|
||||
length: number,
|
||||
callback?: (error: Error | null, bytes: number) => void,
|
||||
): void;
|
||||
/**
|
||||
* Sets or clears the `SO_BROADCAST` socket option. When set to `true`, UDP
|
||||
* packets may be sent to a local interface's broadcast address.
|
||||
*
|
||||
* This method throws `EBADF` if called on an unbound socket.
|
||||
* @since v0.6.9
|
||||
*/
|
||||
setBroadcast(flag: boolean): void;
|
||||
/**
|
||||
* _All references to scope in this section are referring to [IPv6 Zone Indices](https://en.wikipedia.org/wiki/IPv6_address#Scoped_literal_IPv6_addresses), which are defined by [RFC
|
||||
* 4007](https://tools.ietf.org/html/rfc4007). In string form, an IP_
|
||||
* _with a scope index is written as `'IP%scope'` where scope is an interface name_
|
||||
* _or interface number._
|
||||
*
|
||||
* Sets the default outgoing multicast interface of the socket to a chosen
|
||||
* interface or back to system interface selection. The `multicastInterface` must
|
||||
* be a valid string representation of an IP from the socket's family.
|
||||
*
|
||||
* For IPv4 sockets, this should be the IP configured for the desired physical
|
||||
* interface. All packets sent to multicast on the socket will be sent on the
|
||||
* interface determined by the most recent successful use of this call.
|
||||
*
|
||||
* For IPv6 sockets, `multicastInterface` should include a scope to indicate the
|
||||
* interface as in the examples that follow. In IPv6, individual `send` calls can
|
||||
* also use explicit scope in addresses, so only packets sent to a multicast
|
||||
* address without specifying an explicit scope are affected by the most recent
|
||||
* successful use of this call.
|
||||
*
|
||||
* This method throws `EBADF` if called on an unbound socket.
|
||||
*
|
||||
* #### Example: IPv6 outgoing multicast interface
|
||||
*
|
||||
* On most systems, where scope format uses the interface name:
|
||||
*
|
||||
* ```js
|
||||
* const socket = dgram.createSocket('udp6');
|
||||
*
|
||||
* socket.bind(1234, () => {
|
||||
* socket.setMulticastInterface('::%eth1');
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* On Windows, where scope format uses an interface number:
|
||||
*
|
||||
* ```js
|
||||
* const socket = dgram.createSocket('udp6');
|
||||
*
|
||||
* socket.bind(1234, () => {
|
||||
* socket.setMulticastInterface('::%2');
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* #### Example: IPv4 outgoing multicast interface
|
||||
*
|
||||
* All systems use an IP of the host on the desired physical interface:
|
||||
*
|
||||
* ```js
|
||||
* const socket = dgram.createSocket('udp4');
|
||||
*
|
||||
* socket.bind(1234, () => {
|
||||
* socket.setMulticastInterface('10.0.0.2');
|
||||
* });
|
||||
* ```
|
||||
* @since v8.6.0
|
||||
*/
|
||||
setMulticastInterface(multicastInterface: string): void;
|
||||
/**
|
||||
* Sets or clears the `IP_MULTICAST_LOOP` socket option. When set to `true`,
|
||||
* multicast packets will also be received on the local interface.
|
||||
*
|
||||
* This method throws `EBADF` if called on an unbound socket.
|
||||
* @since v0.3.8
|
||||
*/
|
||||
setMulticastLoopback(flag: boolean): boolean;
|
||||
/**
|
||||
* Sets the `IP_MULTICAST_TTL` socket option. While TTL generally stands for
|
||||
* "Time to Live", in this context it specifies the number of IP hops that a
|
||||
* packet is allowed to travel through, specifically for multicast traffic. Each
|
||||
* router or gateway that forwards a packet decrements the TTL. If the TTL is
|
||||
* decremented to 0 by a router, it will not be forwarded.
|
||||
*
|
||||
* The `ttl` argument may be between 0 and 255\. The default on most systems is `1`.
|
||||
*
|
||||
* This method throws `EBADF` if called on an unbound socket.
|
||||
* @since v0.3.8
|
||||
*/
|
||||
setMulticastTTL(ttl: number): number;
|
||||
/**
|
||||
* Sets the `SO_RCVBUF` socket option. Sets the maximum socket receive buffer
|
||||
* in bytes.
|
||||
*
|
||||
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||
* @since v8.7.0
|
||||
*/
|
||||
setRecvBufferSize(size: number): void;
|
||||
/**
|
||||
* Sets the `SO_SNDBUF` socket option. Sets the maximum socket send buffer
|
||||
* in bytes.
|
||||
*
|
||||
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||
* @since v8.7.0
|
||||
*/
|
||||
setSendBufferSize(size: number): void;
|
||||
/**
|
||||
* Sets the `IP_TTL` socket option. While TTL generally stands for "Time to Live",
|
||||
* in this context it specifies the number of IP hops that a packet is allowed to
|
||||
* travel through. Each router or gateway that forwards a packet decrements the
|
||||
* TTL. If the TTL is decremented to 0 by a router, it will not be forwarded.
|
||||
* Changing TTL values is typically done for network probes or when multicasting.
|
||||
*
|
||||
* The `ttl` argument may be between 1 and 255\. The default on most systems
|
||||
* is 64.
|
||||
*
|
||||
* This method throws `EBADF` if called on an unbound socket.
|
||||
* @since v0.1.101
|
||||
*/
|
||||
setTTL(ttl: number): number;
|
||||
/**
|
||||
* By default, binding a socket will cause it to block the Node.js process from
|
||||
* exiting as long as the socket is open. The `socket.unref()` method can be used
|
||||
* to exclude the socket from the reference counting that keeps the Node.js
|
||||
* process active, allowing the process to exit even if the socket is still
|
||||
* listening.
|
||||
*
|
||||
* Calling `socket.unref()` multiple times will have no additional effect.
|
||||
*
|
||||
* The `socket.unref()` method returns a reference to the socket so calls can be
|
||||
* chained.
|
||||
* @since v0.9.1
|
||||
*/
|
||||
unref(): this;
|
||||
/**
|
||||
* Tells the kernel to join a source-specific multicast channel at the given `sourceAddress` and `groupAddress`, using the `multicastInterface` with the `IP_ADD_SOURCE_MEMBERSHIP` socket
|
||||
* option. If the `multicastInterface` argument
|
||||
* is not specified, the operating system will choose one interface and will add
|
||||
* membership to it. To add membership to every available interface, call `socket.addSourceSpecificMembership()` multiple times, once per interface.
|
||||
*
|
||||
* When called on an unbound socket, this method will implicitly bind to a random
|
||||
* port, listening on all interfaces.
|
||||
* @since v13.1.0, v12.16.0
|
||||
*/
|
||||
addSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
|
||||
/**
|
||||
* Instructs the kernel to leave a source-specific multicast channel at the given `sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP` socket option. This method is
|
||||
* automatically called by the kernel when the
|
||||
* socket is closed or the process terminates, so most apps will never have
|
||||
* reason to call this.
|
||||
*
|
||||
* If `multicastInterface` is not specified, the operating system will attempt to
|
||||
* drop membership on all valid interfaces.
|
||||
* @since v13.1.0, v12.16.0
|
||||
*/
|
||||
dropSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
|
||||
/**
|
||||
* Calls `socket.close()` and returns a promise that fulfills when the socket has closed.
|
||||
* @since v20.5.0
|
||||
*/
|
||||
[Symbol.asyncDispose](): Promise<void>;
|
||||
}
|
||||
interface Socket extends InternalEventEmitter<SocketEventMap> {}
|
||||
}
|
||||
declare module "dgram" {
|
||||
export * from "node:dgram";
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @fileoverview Define the abstract class about cursors which iterate tokens.
|
||||
* @author Toru Nagashima
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Exports
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The abstract class about cursors which iterate tokens.
|
||||
*
|
||||
* This class has 2 abstract methods.
|
||||
*
|
||||
* - `current: Token | Comment | null` ... The current token.
|
||||
* - `moveNext(): boolean` ... Moves this cursor to the next token. If the next token didn't exist, it returns `false`.
|
||||
*
|
||||
* This is similar to ES2015 Iterators.
|
||||
* However, Iterators were slow (at 2017-01), so I created this class as similar to C# IEnumerable.
|
||||
*
|
||||
* There are the following known sub classes.
|
||||
*
|
||||
* - ForwardTokenCursor .......... The cursor which iterates tokens only.
|
||||
* - BackwardTokenCursor ......... The cursor which iterates tokens only in reverse.
|
||||
* - ForwardTokenCommentCursor ... The cursor which iterates tokens and comments.
|
||||
* - BackwardTokenCommentCursor .. The cursor which iterates tokens and comments in reverse.
|
||||
* - DecorativeCursor
|
||||
* - FilterCursor ............ The cursor which ignores the specified tokens.
|
||||
* - SkipCursor .............. The cursor which ignores the first few tokens.
|
||||
* - LimitCursor ............. The cursor which limits the count of tokens.
|
||||
*
|
||||
*/
|
||||
module.exports = class Cursor {
|
||||
/**
|
||||
* Initializes this cursor.
|
||||
*/
|
||||
constructor() {
|
||||
this.current = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first token.
|
||||
* This consumes this cursor.
|
||||
* @returns {Token|Comment} The first token or null.
|
||||
*/
|
||||
getOneToken() {
|
||||
return this.moveNext() ? this.current : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first tokens.
|
||||
* This consumes this cursor.
|
||||
* @returns {(Token|Comment)[]} All tokens.
|
||||
*/
|
||||
getAllTokens() {
|
||||
const tokens = [];
|
||||
|
||||
while (this.moveNext()) {
|
||||
tokens.push(this.current);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves this cursor to the next token.
|
||||
* @returns {boolean} `true` if the next token exists.
|
||||
* @abstract
|
||||
*/
|
||||
/* c8 ignore next */
|
||||
// eslint-disable-next-line class-methods-use-this -- Unused
|
||||
moveNext() {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_wrap_native_super.cjs",
|
||||
"module": "../../esm/_wrap_native_super.js"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import * as ts from 'typescript';
|
||||
export declare function checkModifiers(node: ts.Node): void;
|
||||
@@ -0,0 +1,52 @@
|
||||
import type { ScopeManager } from '@typescript-eslint/scope-manager';
|
||||
import type { TSESTree } from '@typescript-eslint/utils';
|
||||
import type { ClassNode, Key, MemberNode } from './types';
|
||||
export declare class Member {
|
||||
/**
|
||||
* The node that declares this member
|
||||
*/
|
||||
readonly node: MemberNode;
|
||||
/**
|
||||
* The resolved, unique key for this member.
|
||||
*/
|
||||
readonly key: Key;
|
||||
/**
|
||||
* The member name, as given in the source code.
|
||||
*/
|
||||
readonly name: string;
|
||||
/**
|
||||
* The node that represents the member name in the source code.
|
||||
* Used for reporting errors.
|
||||
*/
|
||||
readonly nameNode: TSESTree.Node;
|
||||
/**
|
||||
* The number of writes to this member.
|
||||
*/
|
||||
writeCount: number;
|
||||
/**
|
||||
* The number of reads from this member.
|
||||
*/
|
||||
readCount: number;
|
||||
private constructor();
|
||||
static create(node: MemberNode): Member | null;
|
||||
isAccessor(): boolean;
|
||||
isHashPrivate(): boolean;
|
||||
isPrivate(): boolean;
|
||||
isStatic(): boolean;
|
||||
isUsed(): boolean;
|
||||
}
|
||||
export interface ClassScopeResult {
|
||||
/**
|
||||
* The classes name as given in the source code.
|
||||
* If this is `null` then the class is an anonymous class.
|
||||
*/
|
||||
readonly className: string | null;
|
||||
/**
|
||||
* The class's members, keyed by their name
|
||||
*/
|
||||
readonly members: {
|
||||
readonly instance: Map<Key, Member>;
|
||||
readonly static: Map<Key, Member>;
|
||||
};
|
||||
}
|
||||
export declare function analyzeClassMemberUsage(program: TSESTree.Program, scopeManager: ScopeManager): ReadonlyMap<ClassNode, ClassScopeResult>;
|
||||
@@ -0,0 +1,31 @@
|
||||
import { R as ParseResult$1, z as ParserOptions$1 } from "./shared/binding-CVtkJvyl.mjs";
|
||||
import { Program } from "@oxc-project/types";
|
||||
//#region src/parse-ast-index.d.ts
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
type ParseResult = ParseResult$1;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
type ParserOptions = ParserOptions$1;
|
||||
/**
|
||||
* Parse code synchronously and return the AST.
|
||||
*
|
||||
* This function is similar to Rollup's `parseAst` function.
|
||||
* Prefer using {@linkcode parseSync} instead of this function as it has more information in the return value.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
declare function parseAst(sourceText: string, options?: ParserOptions | null, filename?: string): Program;
|
||||
/**
|
||||
* Parse code asynchronously and return the AST.
|
||||
*
|
||||
* This function is similar to Rollup's `parseAstAsync` function.
|
||||
* Prefer using {@linkcode parseAsync} instead of this function as it has more information in the return value.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
declare function parseAstAsync(sourceText: string, options?: ParserOptions | null, filename?: string): Promise<Program>;
|
||||
//#endregion
|
||||
export { ParseResult, ParserOptions, parseAst, parseAstAsync };
|
||||
@@ -0,0 +1,189 @@
|
||||
"use strict";
|
||||
|
||||
var conversions = {};
|
||||
module.exports = conversions;
|
||||
|
||||
function sign(x) {
|
||||
return x < 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
function evenRound(x) {
|
||||
// Round x to the nearest integer, choosing the even integer if it lies halfway between two.
|
||||
if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor)
|
||||
return Math.floor(x);
|
||||
} else {
|
||||
return Math.round(x);
|
||||
}
|
||||
}
|
||||
|
||||
function createNumberConversion(bitLength, typeOpts) {
|
||||
if (!typeOpts.unsigned) {
|
||||
--bitLength;
|
||||
}
|
||||
const lowerBound = typeOpts.unsigned ? 0 : -Math.pow(2, bitLength);
|
||||
const upperBound = Math.pow(2, bitLength) - 1;
|
||||
|
||||
const moduloVal = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength) : Math.pow(2, bitLength);
|
||||
const moduloBound = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength - 1) : Math.pow(2, bitLength - 1);
|
||||
|
||||
return function(V, opts) {
|
||||
if (!opts) opts = {};
|
||||
|
||||
let x = +V;
|
||||
|
||||
if (opts.enforceRange) {
|
||||
if (!Number.isFinite(x)) {
|
||||
throw new TypeError("Argument is not a finite number");
|
||||
}
|
||||
|
||||
x = sign(x) * Math.floor(Math.abs(x));
|
||||
if (x < lowerBound || x > upperBound) {
|
||||
throw new TypeError("Argument is not in byte range");
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
if (!isNaN(x) && opts.clamp) {
|
||||
x = evenRound(x);
|
||||
|
||||
if (x < lowerBound) x = lowerBound;
|
||||
if (x > upperBound) x = upperBound;
|
||||
return x;
|
||||
}
|
||||
|
||||
if (!Number.isFinite(x) || x === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
x = sign(x) * Math.floor(Math.abs(x));
|
||||
x = x % moduloVal;
|
||||
|
||||
if (!typeOpts.unsigned && x >= moduloBound) {
|
||||
return x - moduloVal;
|
||||
} else if (typeOpts.unsigned) {
|
||||
if (x < 0) {
|
||||
x += moduloVal;
|
||||
} else if (x === -0) { // don't return negative zero
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
conversions["void"] = function () {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
conversions["boolean"] = function (val) {
|
||||
return !!val;
|
||||
};
|
||||
|
||||
conversions["byte"] = createNumberConversion(8, { unsigned: false });
|
||||
conversions["octet"] = createNumberConversion(8, { unsigned: true });
|
||||
|
||||
conversions["short"] = createNumberConversion(16, { unsigned: false });
|
||||
conversions["unsigned short"] = createNumberConversion(16, { unsigned: true });
|
||||
|
||||
conversions["long"] = createNumberConversion(32, { unsigned: false });
|
||||
conversions["unsigned long"] = createNumberConversion(32, { unsigned: true });
|
||||
|
||||
conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 });
|
||||
conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 });
|
||||
|
||||
conversions["double"] = function (V) {
|
||||
const x = +V;
|
||||
|
||||
if (!Number.isFinite(x)) {
|
||||
throw new TypeError("Argument is not a finite floating-point value");
|
||||
}
|
||||
|
||||
return x;
|
||||
};
|
||||
|
||||
conversions["unrestricted double"] = function (V) {
|
||||
const x = +V;
|
||||
|
||||
if (isNaN(x)) {
|
||||
throw new TypeError("Argument is NaN");
|
||||
}
|
||||
|
||||
return x;
|
||||
};
|
||||
|
||||
// not quite valid, but good enough for JS
|
||||
conversions["float"] = conversions["double"];
|
||||
conversions["unrestricted float"] = conversions["unrestricted double"];
|
||||
|
||||
conversions["DOMString"] = function (V, opts) {
|
||||
if (!opts) opts = {};
|
||||
|
||||
if (opts.treatNullAsEmptyString && V === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return String(V);
|
||||
};
|
||||
|
||||
conversions["ByteString"] = function (V, opts) {
|
||||
const x = String(V);
|
||||
let c = undefined;
|
||||
for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) {
|
||||
if (c > 255) {
|
||||
throw new TypeError("Argument is not a valid bytestring");
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
};
|
||||
|
||||
conversions["USVString"] = function (V) {
|
||||
const S = String(V);
|
||||
const n = S.length;
|
||||
const U = [];
|
||||
for (let i = 0; i < n; ++i) {
|
||||
const c = S.charCodeAt(i);
|
||||
if (c < 0xD800 || c > 0xDFFF) {
|
||||
U.push(String.fromCodePoint(c));
|
||||
} else if (0xDC00 <= c && c <= 0xDFFF) {
|
||||
U.push(String.fromCodePoint(0xFFFD));
|
||||
} else {
|
||||
if (i === n - 1) {
|
||||
U.push(String.fromCodePoint(0xFFFD));
|
||||
} else {
|
||||
const d = S.charCodeAt(i + 1);
|
||||
if (0xDC00 <= d && d <= 0xDFFF) {
|
||||
const a = c & 0x3FF;
|
||||
const b = d & 0x3FF;
|
||||
U.push(String.fromCodePoint((2 << 15) + (2 << 9) * a + b));
|
||||
++i;
|
||||
} else {
|
||||
U.push(String.fromCodePoint(0xFFFD));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return U.join('');
|
||||
};
|
||||
|
||||
conversions["Date"] = function (V, opts) {
|
||||
if (!(V instanceof Date)) {
|
||||
throw new TypeError("Argument is not a Date object");
|
||||
}
|
||||
if (isNaN(V)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return V;
|
||||
};
|
||||
|
||||
conversions["RegExp"] = function (V, opts) {
|
||||
if (!(V instanceof RegExp)) {
|
||||
V = new RegExp(V);
|
||||
}
|
||||
|
||||
return V;
|
||||
};
|
||||
@@ -0,0 +1,218 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.bn254_weierstrass = exports.bn254 = exports._postPrecompute = exports.bn254_Fr = void 0;
|
||||
/**
|
||||
* bn254, previously known as alt_bn_128, when it had 128-bit security.
|
||||
|
||||
Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits,
|
||||
so the naming has been adjusted to its prime bit count:
|
||||
https://hal.science/hal-01534101/file/main.pdf.
|
||||
Compatible with EIP-196 and EIP-197.
|
||||
|
||||
There are huge compatibility issues in the ecosystem:
|
||||
|
||||
1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128".
|
||||
2. libff has bn128, but it's a different curve with different G2:
|
||||
https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169
|
||||
3. halo2curves bn256 is also incompatible and returns different outputs
|
||||
|
||||
We don't implement Point methods toHex / toBytes.
|
||||
To work around this limitation, has to initialize points on their own from BigInts.
|
||||
Reason it's not implemented is because [there is no standard](https://github.com/privacy-scaling-explorations/halo2curves/issues/109).
|
||||
Points of divergence:
|
||||
|
||||
- Endianness: LE vs BE (byte-swapped)
|
||||
- Flags as first hex bits (similar to BLS) vs no-flags
|
||||
- Imaginary part last in G2 vs first (c0, c1 vs c1, c0)
|
||||
|
||||
The goal of our implementation is to support "Ethereum" variant of the curve,
|
||||
because it at least has specs:
|
||||
|
||||
- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM
|
||||
- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings
|
||||
- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12
|
||||
- The existing implementations are bad. Some are deprecated:
|
||||
- https://github.com/paritytech/bn (old version)
|
||||
- https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn)
|
||||
- https://github.com/zcash-hackworks/bn
|
||||
- https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs
|
||||
- Python implementations use different towers and produce different Fp12 outputs:
|
||||
- https://github.com/ethereum/py_pairing
|
||||
- https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py
|
||||
- Points are encoded differently in different implementations
|
||||
|
||||
### Params
|
||||
Seed (X): 4965661367192848881
|
||||
Fr: (36x⁴+36x³+18x²+6x+1)
|
||||
Fp: (36x⁴+36x³+24x²+6x+1)
|
||||
(E / Fp ): Y² = X³+3
|
||||
(Et / Fp²): Y² = X³+3/(u+9) (D-type twist)
|
||||
Ate loop size: 6x+2
|
||||
|
||||
### Towers
|
||||
- Fp²[u] = Fp/u²+1
|
||||
- Fp⁶[v] = Fp²/v³-9-u
|
||||
- Fp¹²[w] = Fp⁶/w²-v
|
||||
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
||||
const bls_ts_1 = require("./abstract/bls.js");
|
||||
const modular_ts_1 = require("./abstract/modular.js");
|
||||
const tower_ts_1 = require("./abstract/tower.js");
|
||||
const weierstrass_ts_1 = require("./abstract/weierstrass.js");
|
||||
const utils_ts_1 = require("./utils.js");
|
||||
// prettier-ignore
|
||||
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
||||
const _6n = BigInt(6);
|
||||
const BN_X = BigInt('4965661367192848881');
|
||||
const BN_X_LEN = (0, utils_ts_1.bitLen)(BN_X);
|
||||
const SIX_X_SQUARED = _6n * BN_X ** _2n;
|
||||
const bn254_G1_CURVE = {
|
||||
p: BigInt('0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47'),
|
||||
n: BigInt('0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001'),
|
||||
h: _1n,
|
||||
a: _0n,
|
||||
b: _3n,
|
||||
Gx: _1n,
|
||||
Gy: BigInt(2),
|
||||
};
|
||||
// r == n
|
||||
// Finite field over r. It's for convenience and is not used in the code below.
|
||||
exports.bn254_Fr = (0, modular_ts_1.Field)(bn254_G1_CURVE.n);
|
||||
// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE)
|
||||
const Fp2B = {
|
||||
c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'),
|
||||
c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'),
|
||||
};
|
||||
const { Fp, Fp2, Fp6, Fp12 } = (0, tower_ts_1.tower12)({
|
||||
ORDER: bn254_G1_CURVE.p,
|
||||
X_LEN: BN_X_LEN,
|
||||
FP2_NONRESIDUE: [BigInt(9), _1n],
|
||||
Fp2mulByB: (num) => Fp2.mul(num, Fp2B),
|
||||
Fp12finalExponentiate: (num) => {
|
||||
const powMinusX = (num) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X));
|
||||
const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num));
|
||||
const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0);
|
||||
const y1 = Fp12._cyclotomicSquare(powMinusX(r));
|
||||
const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1);
|
||||
const y4 = powMinusX(y2);
|
||||
const y6 = powMinusX(Fp12._cyclotomicSquare(y4));
|
||||
const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2));
|
||||
const y9 = Fp12.mul(y8, y1);
|
||||
return Fp12.mul(Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), Fp12.mul(Fp12.frobeniusMap(y8, 2), Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r))));
|
||||
},
|
||||
});
|
||||
// END OF CURVE FIELDS
|
||||
const { G2psi, psi } = (0, tower_ts_1.psiFrobenius)(Fp, Fp2, Fp2.NONRESIDUE);
|
||||
/*
|
||||
No hashToCurve for now (and signatures):
|
||||
|
||||
- RFC 9380 doesn't mention bn254 and doesn't provide test vectors
|
||||
- Overall seems like nobody is using BLS signatures on top of bn254
|
||||
- Seems like it can utilize SVDW, which is not implemented yet
|
||||
*/
|
||||
const htfDefaults = Object.freeze({
|
||||
// DST: a domain separation tag defined in section 2.2.5
|
||||
DST: 'BN254G2_XMD:SHA-256_SVDW_RO_',
|
||||
encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_',
|
||||
p: Fp.ORDER,
|
||||
m: 2,
|
||||
k: 128,
|
||||
expand: 'xmd',
|
||||
hash: sha2_js_1.sha256,
|
||||
});
|
||||
const _postPrecompute = (Rx, Ry, Rz, Qx, Qy, pointAdd) => {
|
||||
const q = psi(Qx, Qy);
|
||||
({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1]));
|
||||
const q2 = psi(q[0], q[1]);
|
||||
pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1]));
|
||||
};
|
||||
exports._postPrecompute = _postPrecompute;
|
||||
// cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1
|
||||
const bn254_G2_CURVE = {
|
||||
p: Fp2.ORDER,
|
||||
n: bn254_G1_CURVE.n,
|
||||
h: BigInt('0x30644e72e131a029b85045b68181585e06ceecda572a2489345f2299c0f9fa8d'),
|
||||
a: Fp2.ZERO,
|
||||
b: Fp2B,
|
||||
Gx: Fp2.fromBigTuple([
|
||||
BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'),
|
||||
BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'),
|
||||
]),
|
||||
Gy: Fp2.fromBigTuple([
|
||||
BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'),
|
||||
BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'),
|
||||
]),
|
||||
};
|
||||
/**
|
||||
* bn254 (a.k.a. alt_bn128) pairing-friendly curve.
|
||||
* Contains G1 / G2 operations and pairings.
|
||||
*/
|
||||
exports.bn254 = (0, bls_ts_1.bls)({
|
||||
// Fields
|
||||
fields: { Fp, Fp2, Fp6, Fp12, Fr: exports.bn254_Fr },
|
||||
G1: {
|
||||
...bn254_G1_CURVE,
|
||||
Fp,
|
||||
htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' },
|
||||
wrapPrivateKey: true,
|
||||
allowInfinityPoint: true,
|
||||
mapToCurve: utils_ts_1.notImplemented,
|
||||
fromBytes: utils_ts_1.notImplemented,
|
||||
toBytes: utils_ts_1.notImplemented,
|
||||
ShortSignature: {
|
||||
fromBytes: utils_ts_1.notImplemented,
|
||||
fromHex: utils_ts_1.notImplemented,
|
||||
toBytes: utils_ts_1.notImplemented,
|
||||
toRawBytes: utils_ts_1.notImplemented,
|
||||
toHex: utils_ts_1.notImplemented,
|
||||
},
|
||||
},
|
||||
G2: {
|
||||
...bn254_G2_CURVE,
|
||||
Fp: Fp2,
|
||||
hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'),
|
||||
htfDefaults: { ...htfDefaults },
|
||||
wrapPrivateKey: true,
|
||||
allowInfinityPoint: true,
|
||||
isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P
|
||||
mapToCurve: utils_ts_1.notImplemented,
|
||||
fromBytes: utils_ts_1.notImplemented,
|
||||
toBytes: utils_ts_1.notImplemented,
|
||||
Signature: {
|
||||
fromBytes: utils_ts_1.notImplemented,
|
||||
fromHex: utils_ts_1.notImplemented,
|
||||
toBytes: utils_ts_1.notImplemented,
|
||||
toRawBytes: utils_ts_1.notImplemented,
|
||||
toHex: utils_ts_1.notImplemented,
|
||||
},
|
||||
},
|
||||
params: {
|
||||
ateLoopSize: BN_X * _6n + _2n,
|
||||
r: exports.bn254_Fr.ORDER,
|
||||
xNegative: false,
|
||||
twistType: 'divisive',
|
||||
},
|
||||
htfDefaults,
|
||||
hash: sha2_js_1.sha256,
|
||||
postPrecompute: exports._postPrecompute,
|
||||
});
|
||||
/**
|
||||
* bn254 weierstrass curve with ECDSA.
|
||||
* This is very rare and probably not used anywhere.
|
||||
* Instead, you should use G1 / G2, defined above.
|
||||
* @deprecated
|
||||
*/
|
||||
exports.bn254_weierstrass = (0, weierstrass_ts_1.weierstrass)({
|
||||
a: BigInt(0),
|
||||
b: BigInt(3),
|
||||
Fp,
|
||||
n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'),
|
||||
Gx: BigInt(1),
|
||||
Gy: BigInt(2),
|
||||
h: BigInt(1),
|
||||
hash: sha2_js_1.sha256,
|
||||
});
|
||||
//# sourceMappingURL=bn254.js.map
|
||||
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* @fileoverview Rule to flag use of alert, confirm, prompt
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const {
|
||||
getStaticPropertyName: getPropertyName,
|
||||
getVariableByName,
|
||||
skipChainExpression,
|
||||
} = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks if the given name is a prohibited identifier.
|
||||
* @param {string} name The name to check
|
||||
* @returns {boolean} Whether or not the name is prohibited.
|
||||
*/
|
||||
function isProhibitedIdentifier(name) {
|
||||
return /^(?:alert|confirm|prompt)$/u.test(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the eslint-scope reference in the given scope.
|
||||
* @param {Object} scope The scope to search.
|
||||
* @param {ASTNode} node The identifier node.
|
||||
* @returns {Reference|null} Returns the found reference or null if none were found.
|
||||
*/
|
||||
function findReference(scope, node) {
|
||||
const references = scope.references.filter(
|
||||
reference =>
|
||||
reference.identifier.range[0] === node.range[0] &&
|
||||
reference.identifier.range[1] === node.range[1],
|
||||
);
|
||||
|
||||
if (references.length === 1) {
|
||||
return references[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given identifier node is shadowed in the given scope.
|
||||
* @param {Object} scope The current scope.
|
||||
* @param {string} node The identifier node to check
|
||||
* @returns {boolean} Whether or not the name is shadowed.
|
||||
*/
|
||||
function isShadowed(scope, node) {
|
||||
const reference = findReference(scope, node);
|
||||
|
||||
return (
|
||||
reference && reference.resolved && reference.resolved.defs.length > 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given identifier node is a ThisExpression in the global scope or the global window property.
|
||||
* @param {Object} scope The current scope.
|
||||
* @param {string} node The identifier node to check
|
||||
* @returns {boolean} Whether or not the node is a reference to the global object.
|
||||
*/
|
||||
function isGlobalThisReferenceOrGlobalWindow(scope, node) {
|
||||
if (scope.type === "global" && node.type === "ThisExpression") {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
node.type === "Identifier" &&
|
||||
(node.name === "window" ||
|
||||
(node.name === "globalThis" &&
|
||||
getVariableByName(scope, "globalThis")))
|
||||
) {
|
||||
return !isShadowed(scope, node);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "Disallow the use of `alert`, `confirm`, and `prompt`",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-alert",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
unexpected: "Unexpected {{name}}.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
return {
|
||||
CallExpression(node) {
|
||||
const callee = skipChainExpression(node.callee),
|
||||
currentScope = sourceCode.getScope(node);
|
||||
|
||||
// without window.
|
||||
if (callee.type === "Identifier") {
|
||||
const name = callee.name;
|
||||
|
||||
if (
|
||||
!isShadowed(currentScope, callee) &&
|
||||
isProhibitedIdentifier(callee.name)
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unexpected",
|
||||
data: { name },
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
callee.type === "MemberExpression" &&
|
||||
isGlobalThisReferenceOrGlobalWindow(
|
||||
currentScope,
|
||||
callee.object,
|
||||
)
|
||||
) {
|
||||
const name = getPropertyName(callee);
|
||||
|
||||
if (isProhibitedIdentifier(name)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unexpected",
|
||||
data: { name },
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user