WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getTypeFlags = getTypeFlags;
|
||||
exports.isTypeFlagSet = isTypeFlagSet;
|
||||
const tsutils = __importStar(require("ts-api-utils"));
|
||||
const ts = __importStar(require("typescript"));
|
||||
const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown;
|
||||
/**
|
||||
* Gets all of the type flags in a type, iterating through unions automatically.
|
||||
*/
|
||||
function getTypeFlags(type) {
|
||||
// @ts-expect-error Since typescript 5.0, this is invalid, but uses 0 as the default value of TypeFlags.
|
||||
let flags = 0;
|
||||
for (const t of tsutils.unionConstituents(type)) {
|
||||
flags |= t.flags;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
/**
|
||||
* @param flagsToCheck The composition of one or more `ts.TypeFlags`.
|
||||
* @param isReceiver Whether the type is a receiving type (e.g. the type of a
|
||||
* called function's parameter).
|
||||
* @remarks
|
||||
* Note that if the type is a union, this function will decompose it into the
|
||||
* parts and get the flags of every union constituent. If this is not desired,
|
||||
* use the `isTypeFlag` function from tsutils.
|
||||
*/
|
||||
function isTypeFlagSet(type, flagsToCheck,
|
||||
/** @deprecated This params is not used and will be removed in the future.*/
|
||||
isReceiver) {
|
||||
const flags = getTypeFlags(type);
|
||||
// eslint-disable-next-line @typescript-eslint/no-deprecated -- not used
|
||||
if (isReceiver && flags & ANY_OR_UNKNOWN) {
|
||||
return true;
|
||||
}
|
||||
return (flags & flagsToCheck) !== 0;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Evan Wallace
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const indexes = require('../lib/indexes')
|
||||
|
||||
for (const index of Object.keys(indexes)) {
|
||||
test(`${index} is lock free`, function () {
|
||||
assert.strictEqual(Atomics.isLockFree(indexes[index]), true)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { TSESLint } from '@typescript-eslint/utils';
|
||||
export type Options = [
|
||||
{
|
||||
checkNever: boolean;
|
||||
}
|
||||
];
|
||||
declare const _default: TSESLint.RuleModule<"meaninglessVoidOperator" | "removeVoid", Options, import("../../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,52 @@
|
||||
# path-exists [](https://travis-ci.org/sindresorhus/path-exists)
|
||||
|
||||
> Check if a path exists
|
||||
|
||||
NOTE: `fs.existsSync` has been un-deprecated in Node.js since 6.8.0. If you only need to check synchronously, this module is not needed.
|
||||
|
||||
While [`fs.exists()`](https://nodejs.org/api/fs.html#fs_fs_exists_path_callback) is being [deprecated](https://github.com/iojs/io.js/issues/103), there's still a genuine use-case of being able to check if a path exists for other purposes than doing IO with it.
|
||||
|
||||
Never use this before handling a file though:
|
||||
|
||||
> In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to `fs.exists()` and `fs.open()`. Just open the file and handle the error when it's not there.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install path-exists
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
// foo.js
|
||||
const pathExists = require('path-exists');
|
||||
|
||||
(async () => {
|
||||
console.log(await pathExists('foo.js'));
|
||||
//=> true
|
||||
})();
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### pathExists(path)
|
||||
|
||||
Returns a `Promise<boolean>` of whether the path exists.
|
||||
|
||||
### pathExists.sync(path)
|
||||
|
||||
Returns a `boolean` of whether the path exists.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [path-exists-cli](https://github.com/sindresorhus/path-exists-cli) - CLI for this module
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
@@ -0,0 +1,29 @@
|
||||
declare const _default: {
|
||||
extends: string[];
|
||||
rules: {
|
||||
'@typescript-eslint/adjacent-overload-signatures': "error";
|
||||
'@typescript-eslint/array-type': "error";
|
||||
'@typescript-eslint/ban-tslint-comment': "error";
|
||||
'@typescript-eslint/class-literal-property-style': "error";
|
||||
'@typescript-eslint/consistent-generic-constructors': "error";
|
||||
'@typescript-eslint/consistent-indexed-object-style': "error";
|
||||
'@typescript-eslint/consistent-type-assertions': "error";
|
||||
'@typescript-eslint/consistent-type-definitions': "error";
|
||||
'dot-notation': "off";
|
||||
'@typescript-eslint/dot-notation': "error";
|
||||
'@typescript-eslint/no-confusing-non-null-assertion': "error";
|
||||
'no-empty-function': "off";
|
||||
'@typescript-eslint/no-empty-function': "error";
|
||||
'@typescript-eslint/no-inferrable-types': "error";
|
||||
'@typescript-eslint/non-nullable-type-assertion-style': "error";
|
||||
'@typescript-eslint/prefer-find': "error";
|
||||
'@typescript-eslint/prefer-for-of': "error";
|
||||
'@typescript-eslint/prefer-function-type': "error";
|
||||
'@typescript-eslint/prefer-includes': "error";
|
||||
'@typescript-eslint/prefer-nullish-coalescing': "error";
|
||||
'@typescript-eslint/prefer-optional-chain': "error";
|
||||
'@typescript-eslint/prefer-regexp-exec': "error";
|
||||
'@typescript-eslint/prefer-string-starts-ends-with': "error";
|
||||
};
|
||||
};
|
||||
export = _default;
|
||||
@@ -0,0 +1,794 @@
|
||||
// @ts-self-types="./index.d.ts"
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
/**
|
||||
* @fileoverview defineConfig helper
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @import * as $eslintcore from "@eslint/core"; */
|
||||
/** @typedef {$eslintcore.ConfigObject} ConfigObject */
|
||||
/** @typedef {$eslintcore.LegacyConfigObject} LegacyConfig */
|
||||
/** @typedef {$eslintcore.Plugin} Plugin */
|
||||
/** @typedef {$eslintcore.RuleConfig} RuleConfig */
|
||||
/** @import * as $typests from "./types.ts"; */
|
||||
/** @typedef {$typests.Config} Config */
|
||||
/** @typedef {$typests.ExtendsElement} ExtendsElement */
|
||||
/** @typedef {$typests.ExtensionConfigObject} ExtensionConfigObject */
|
||||
/** @typedef {$typests.SimpleExtendsElement} SimpleExtendsElement */
|
||||
/** @typedef {$typests.ConfigWithExtends} ConfigWithExtends */
|
||||
/** @typedef {$typests.InfiniteArray<ConfigObject>} InfiniteConfigArray */
|
||||
/** @typedef {$typests.ConfigWithExtendsArray} ConfigWithExtendsArray */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const eslintrcKeys = [
|
||||
"env",
|
||||
"extends",
|
||||
"globals",
|
||||
"ignorePatterns",
|
||||
"noInlineConfig",
|
||||
"overrides",
|
||||
"parser",
|
||||
"parserOptions",
|
||||
"reportUnusedDisableDirectives",
|
||||
"root",
|
||||
];
|
||||
|
||||
const allowedGlobalIgnoreKeys = new Set(["basePath", "ignores", "name"]);
|
||||
|
||||
/**
|
||||
* Gets the name of a config object.
|
||||
* @param {ConfigObject} config The config object.
|
||||
* @param {string} indexPath The index path of the config object.
|
||||
* @return {string} The name of the config object.
|
||||
*/
|
||||
function getConfigName(config, indexPath) {
|
||||
if (config.name) {
|
||||
return config.name;
|
||||
}
|
||||
|
||||
return `UserConfig${indexPath}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of an extension.
|
||||
* @param {SimpleExtendsElement} extension The extension.
|
||||
* @param {string} indexPath The index of the extension.
|
||||
* @return {string} The name of the extension.
|
||||
*/
|
||||
function getExtensionName(extension, indexPath) {
|
||||
if (typeof extension === "string") {
|
||||
return extension;
|
||||
}
|
||||
|
||||
if (extension.name) {
|
||||
return extension.name;
|
||||
}
|
||||
|
||||
return `ExtendedConfig${indexPath}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a config object is a legacy config.
|
||||
* @param {ConfigObject|LegacyConfig} config The config object to check.
|
||||
* @return {config is LegacyConfig} `true` if the config object is a legacy config.
|
||||
*/
|
||||
function isLegacyConfig(config) {
|
||||
// eslintrc's plugins must be an array; while flat config's must be an object.
|
||||
if (Array.isArray(config.plugins)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const key of eslintrcKeys) {
|
||||
if (key in config) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a config object is a global ignores config.
|
||||
* @param {ConfigObject} config The config object to check.
|
||||
* @return {boolean} `true` if the config object is a global ignores config.
|
||||
*/
|
||||
function isGlobalIgnores(config) {
|
||||
return Object.keys(config).every(key => allowedGlobalIgnoreKeys.has(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a plugin member ID (rule, processor, etc.) and returns
|
||||
* the namespace and member name.
|
||||
* @param {string} id The ID to parse.
|
||||
* @returns {{namespace:string, name:string}} The namespace and member name.
|
||||
*/
|
||||
function getPluginMember(id) {
|
||||
const firstSlashIndex = id.indexOf("/");
|
||||
|
||||
if (firstSlashIndex === -1) {
|
||||
return { namespace: "", name: id };
|
||||
}
|
||||
|
||||
let namespace = id.slice(0, firstSlashIndex);
|
||||
|
||||
/*
|
||||
* Special cases:
|
||||
* 1. The namespace is `@`, that means it's referring to the
|
||||
* core plugin so `@` is the full namespace.
|
||||
* 2. The namespace starts with `@`, that means it's referring to
|
||||
* an npm scoped package. That means the namespace is the scope
|
||||
* and the package name (i.e., `@eslint/core`).
|
||||
*/
|
||||
if (namespace[0] === "@" && namespace !== "@") {
|
||||
const secondSlashIndex = id.indexOf("/", firstSlashIndex + 1);
|
||||
if (secondSlashIndex !== -1) {
|
||||
namespace = id.slice(0, secondSlashIndex);
|
||||
return { namespace, name: id.slice(secondSlashIndex + 1) };
|
||||
}
|
||||
}
|
||||
|
||||
const name = id.slice(firstSlashIndex + 1);
|
||||
|
||||
return { namespace, name };
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the plugin config by replacing the namespace with the plugin namespace.
|
||||
* @param {string} userNamespace The namespace of the plugin.
|
||||
* @param {Plugin} plugin The plugin config object.
|
||||
* @param {ConfigObject} config The config object to normalize.
|
||||
* @return {ConfigObject} The normalized config object.
|
||||
*/
|
||||
function normalizePluginConfig(userNamespace, plugin, config) {
|
||||
const pluginNamespace = plugin.meta?.namespace;
|
||||
|
||||
// don't do anything if the plugin doesn't have a namespace or rules
|
||||
if (
|
||||
!pluginNamespace ||
|
||||
pluginNamespace === userNamespace ||
|
||||
(!config.rules && !config.processor && !config.language)
|
||||
) {
|
||||
return config;
|
||||
}
|
||||
|
||||
const result = { ...config };
|
||||
|
||||
// update the rules
|
||||
if (result.rules) {
|
||||
const ruleIds = Object.keys(result.rules);
|
||||
|
||||
/** @type {Record<string,RuleConfig|undefined>} */
|
||||
const newRules = {};
|
||||
|
||||
for (let i = 0; i < ruleIds.length; i++) {
|
||||
const ruleId = ruleIds[i];
|
||||
const { namespace: ruleNamespace, name: ruleName } =
|
||||
getPluginMember(ruleId);
|
||||
|
||||
if (ruleNamespace === pluginNamespace) {
|
||||
newRules[`${userNamespace}/${ruleName}`] = result.rules[ruleId];
|
||||
} else {
|
||||
newRules[ruleId] = result.rules[ruleId];
|
||||
}
|
||||
}
|
||||
|
||||
result.rules = newRules;
|
||||
}
|
||||
|
||||
// update the processor
|
||||
|
||||
if (typeof result.processor === "string") {
|
||||
const { namespace: processorNamespace, name: processorName } =
|
||||
getPluginMember(result.processor);
|
||||
|
||||
if (processorNamespace) {
|
||||
if (processorNamespace === pluginNamespace) {
|
||||
result.processor = `${userNamespace}/${processorName}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update the language
|
||||
if (typeof result.language === "string") {
|
||||
const { namespace: languageNamespace, name: languageName } =
|
||||
getPluginMember(result.language);
|
||||
|
||||
if (languageNamespace === pluginNamespace) {
|
||||
result.language = `${userNamespace}/${languageName}`;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deeply normalizes a plugin config, traversing recursively into an arrays.
|
||||
* @param {string} userPluginNamespace The namespace of the plugin.
|
||||
* @param {Plugin} plugin The plugin object.
|
||||
* @param {ConfigObject|LegacyConfig|(ConfigObject|LegacyConfig)[]} pluginConfig The plugin config to normalize.
|
||||
* @param {string} pluginConfigName The name of the plugin config.
|
||||
* @return {InfiniteConfigArray} The normalized plugin config.
|
||||
* @throws {TypeError} If the plugin config is a legacy config.
|
||||
*/
|
||||
function deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
pluginConfig,
|
||||
pluginConfigName,
|
||||
) {
|
||||
// if it's an array then it's definitely a new config
|
||||
if (Array.isArray(pluginConfig)) {
|
||||
return pluginConfig.map(pluginSubConfig =>
|
||||
deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
pluginSubConfig,
|
||||
pluginConfigName,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// if it's a legacy config, throw an error
|
||||
if (isLegacyConfig(pluginConfig)) {
|
||||
throw new TypeError(
|
||||
`Plugin config "${pluginConfigName}" is an eslintrc config and cannot be used in this context.`,
|
||||
);
|
||||
}
|
||||
|
||||
return normalizePluginConfig(userPluginNamespace, plugin, pluginConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a plugin config by name in the given config.
|
||||
* @param {ConfigObject} config The config object.
|
||||
* @param {string} pluginConfigName The name of the plugin config.
|
||||
* @return {InfiniteConfigArray} The plugin config.
|
||||
* @throws {TypeError} If the plugin config is not found or is a legacy config.
|
||||
*/
|
||||
function findPluginConfig(config, pluginConfigName) {
|
||||
const { namespace: userPluginNamespace, name: configName } =
|
||||
getPluginMember(pluginConfigName);
|
||||
const plugin = config.plugins?.[userPluginNamespace];
|
||||
|
||||
if (!plugin) {
|
||||
throw new TypeError(`Plugin "${userPluginNamespace}" not found.`);
|
||||
}
|
||||
|
||||
const directConfig = plugin.configs?.[configName];
|
||||
|
||||
// Prefer direct config, but fall back to flat config if available
|
||||
if (directConfig) {
|
||||
// Arrays are always flat configs, and non-legacy configs can be used directly
|
||||
if (Array.isArray(directConfig) || !isLegacyConfig(directConfig)) {
|
||||
return deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
directConfig,
|
||||
pluginConfigName,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a legacy config, or the config does not exist => look for the flat version
|
||||
const flatConfig = plugin.configs?.[`flat/${configName}`];
|
||||
if (
|
||||
flatConfig &&
|
||||
(Array.isArray(flatConfig) || !isLegacyConfig(flatConfig))
|
||||
) {
|
||||
return deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
flatConfig,
|
||||
pluginConfigName,
|
||||
);
|
||||
}
|
||||
|
||||
// If we get here, then the config was either not found or is a legacy config
|
||||
const message =
|
||||
directConfig || flatConfig
|
||||
? `Plugin config "${configName}" in plugin "${userPluginNamespace}" is an eslintrc config and cannot be used in this context.`
|
||||
: `Plugin config "${configName}" not found in plugin "${userPluginNamespace}".`;
|
||||
throw new TypeError(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens an array while keeping track of the index path.
|
||||
* @param {any[]} configList The array to traverse.
|
||||
* @param {string} indexPath The index path of the value in a multidimensional array.
|
||||
* @return {IterableIterator<{indexPath:string, value:any}>} The flattened list of values.
|
||||
*/
|
||||
function* flatTraverse(configList, indexPath = "") {
|
||||
for (let i = 0; i < configList.length; i++) {
|
||||
const newIndexPath = indexPath ? `${indexPath}[${i}]` : `[${i}]`;
|
||||
|
||||
// if it's an array then traverse it as well
|
||||
if (Array.isArray(configList[i])) {
|
||||
yield* flatTraverse(configList[i], newIndexPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
yield { indexPath: newIndexPath, value: configList[i] };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends a list of config files by creating every combination of base and extension files.
|
||||
* @param {(string|string[])[]} [baseFiles] The base files.
|
||||
* @param {(string|string[])[]} [extensionFiles] The extension files.
|
||||
* @return {(string|string[])[]} The extended files.
|
||||
*/
|
||||
function extendConfigFiles(baseFiles = [], extensionFiles = []) {
|
||||
if (!extensionFiles.length) {
|
||||
return baseFiles.concat();
|
||||
}
|
||||
|
||||
if (!baseFiles.length) {
|
||||
return extensionFiles.concat();
|
||||
}
|
||||
|
||||
/** @type {(string|string[])[]} */
|
||||
const result = [];
|
||||
|
||||
for (const baseFile of baseFiles) {
|
||||
for (const extensionFile of extensionFiles) {
|
||||
/*
|
||||
* Each entry can be a string or array of strings. The end result
|
||||
* needs to be an array of strings, so we need to be sure to include
|
||||
* all of the items when there's an array.
|
||||
*/
|
||||
|
||||
const entry = [];
|
||||
|
||||
if (Array.isArray(baseFile)) {
|
||||
entry.push(...baseFile);
|
||||
} else {
|
||||
entry.push(baseFile);
|
||||
}
|
||||
|
||||
if (Array.isArray(extensionFile)) {
|
||||
entry.push(...extensionFile);
|
||||
} else {
|
||||
entry.push(extensionFile);
|
||||
}
|
||||
|
||||
result.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends a config object with another config object.
|
||||
* @param {ConfigObject} baseConfig The base config object.
|
||||
* @param {string} baseConfigName The name of the base config object.
|
||||
* @param {ConfigObject} extension The extension config object.
|
||||
* @param {string} extensionName The index of the extension config object.
|
||||
* @return {ConfigObject} The extended config object.
|
||||
*/
|
||||
function extendConfig(baseConfig, baseConfigName, extension, extensionName) {
|
||||
const result = { ...extension };
|
||||
|
||||
// for global ignores there is no further work to be done, we just keep everything
|
||||
if (!isGlobalIgnores(extension)) {
|
||||
// for files we need to create every combination of base and extension files
|
||||
if (baseConfig.files) {
|
||||
result.files = extendConfigFiles(baseConfig.files, extension.files);
|
||||
}
|
||||
|
||||
// for ignores we just concatenation the extension ignores onto the base ignores
|
||||
if (baseConfig.ignores) {
|
||||
result.ignores = baseConfig.ignores.concat(extension.ignores ?? []);
|
||||
}
|
||||
}
|
||||
|
||||
result.name = `${baseConfigName} > ${extensionName}`;
|
||||
|
||||
if (baseConfig.basePath) {
|
||||
result.basePath = baseConfig.basePath;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a list of extends elements.
|
||||
* @param {ConfigWithExtends} config The config object.
|
||||
* @param {WeakMap<ConfigObject, string>} configNames The map of config objects to their names.
|
||||
* @return {ConfigObject[]} The flattened list of config objects.
|
||||
* @throws {TypeError} If the `extends` property is not an array or if nested `extends` is found.
|
||||
*/
|
||||
function processExtends(config, configNames) {
|
||||
if (!config.extends) {
|
||||
return [config];
|
||||
}
|
||||
|
||||
if (!Array.isArray(config.extends)) {
|
||||
throw new TypeError("The `extends` property must be an array.");
|
||||
}
|
||||
|
||||
const {
|
||||
/** @type {ConfigObject[]} */
|
||||
extends: extendsList,
|
||||
|
||||
/** @type {ConfigObject} */
|
||||
...configObject
|
||||
} = config;
|
||||
|
||||
const extensionNames = new WeakMap();
|
||||
|
||||
// replace strings with the actual configs
|
||||
const objectExtends = extendsList.map(extendsElement => {
|
||||
if (typeof extendsElement === "string") {
|
||||
const pluginConfig = findPluginConfig(config, extendsElement);
|
||||
|
||||
// assign names
|
||||
if (Array.isArray(pluginConfig)) {
|
||||
pluginConfig.forEach((pluginConfigElement, index) => {
|
||||
extensionNames.set(
|
||||
pluginConfigElement,
|
||||
`${extendsElement}[${index}]`,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
extensionNames.set(pluginConfig, extendsElement);
|
||||
}
|
||||
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
return /** @type {ConfigObject} */ (extendsElement);
|
||||
});
|
||||
|
||||
const result = [];
|
||||
|
||||
for (const { indexPath, value: extendsElement } of flatTraverse(
|
||||
objectExtends,
|
||||
)) {
|
||||
const extension = /** @type {ConfigObject} */ (extendsElement);
|
||||
|
||||
if ("basePath" in extension) {
|
||||
throw new TypeError("'basePath' in `extends` is not allowed.");
|
||||
}
|
||||
|
||||
if ("extends" in extension) {
|
||||
throw new TypeError("Nested 'extends' is not allowed.");
|
||||
}
|
||||
|
||||
const baseConfigName = /** @type {string} */ (configNames.get(config));
|
||||
const extensionName =
|
||||
extensionNames.get(extendsElement) ??
|
||||
getExtensionName(extendsElement, indexPath);
|
||||
|
||||
result.push(
|
||||
extendConfig(
|
||||
configObject,
|
||||
baseConfigName,
|
||||
extension,
|
||||
extensionName,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the base config object has only `ignores` and `extends`, then
|
||||
* removing `extends` turns it into a global ignores, which is not what
|
||||
* we want. So we need to check if the base config object is a global ignores
|
||||
* and if so, we don't add it to the array.
|
||||
*
|
||||
* (The other option would be to add a `files` entry, but that would result
|
||||
* in a config that didn't actually do anything because there are no
|
||||
* other keys in the config.)
|
||||
*/
|
||||
if (!isGlobalIgnores(configObject)) {
|
||||
result.push(configObject);
|
||||
}
|
||||
|
||||
return result.flat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a list of config objects and arrays.
|
||||
* @param {ConfigWithExtends[]} configList The list of config objects and arrays.
|
||||
* @param {WeakMap<ConfigObject, string>} configNames The map of config objects to their names.
|
||||
* @return {ConfigObject[]} The flattened list of config objects.
|
||||
*/
|
||||
function processConfigList(configList, configNames) {
|
||||
return configList.flatMap(config => processExtends(config, configNames));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helper function to define a config array.
|
||||
* @param {ConfigWithExtendsArray} args The arguments to the function.
|
||||
* @returns {ConfigObject[]} The config array.
|
||||
* @throws {TypeError} If no arguments are provided or if an argument is not an object.
|
||||
*/
|
||||
function defineConfig(...args) {
|
||||
const configNames = new WeakMap();
|
||||
const configs = [];
|
||||
|
||||
if (args.length === 0) {
|
||||
throw new TypeError("Expected one or more arguments.");
|
||||
}
|
||||
|
||||
// first flatten the list of configs and get the names
|
||||
for (const { indexPath, value } of flatTraverse(args)) {
|
||||
if (typeof value !== "object" || value === null) {
|
||||
throw new TypeError(
|
||||
`Expected an object but received ${String(value)}.`,
|
||||
);
|
||||
}
|
||||
|
||||
const config = /** @type {ConfigWithExtends} */ (value);
|
||||
|
||||
// save config name for easy reference later
|
||||
configNames.set(config, getConfigName(config, indexPath));
|
||||
configs.push(config);
|
||||
}
|
||||
|
||||
return processConfigList(configs, configNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview Global ignores helper function.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
let globalIgnoreCount = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a global ignores config with the given patterns.
|
||||
* @param {string[]} ignorePatterns The ignore patterns.
|
||||
* @param {string} [name] The name of the global ignores config.
|
||||
* @returns {ConfigObject} The global ignores config.
|
||||
* @throws {TypeError} If ignorePatterns is not an array or if it is empty.
|
||||
*/
|
||||
function globalIgnores(ignorePatterns, name) {
|
||||
if (!Array.isArray(ignorePatterns)) {
|
||||
throw new TypeError("ignorePatterns must be an array");
|
||||
}
|
||||
|
||||
if (ignorePatterns.length === 0) {
|
||||
throw new TypeError("ignorePatterns must contain at least one pattern");
|
||||
}
|
||||
|
||||
const id = globalIgnoreCount++;
|
||||
|
||||
return {
|
||||
name: name || `globalIgnores ${id}`,
|
||||
ignores: ignorePatterns,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview Ignore file utilities for the config-helpers package.
|
||||
* This file was forked from the source code for the compat package.
|
||||
*
|
||||
* @author Nicholas C. Zakas
|
||||
* @author Kirk Waiblinger
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {object} IncludeIgnoreFileOptionsObject
|
||||
* @property {boolean} [gitignoreResolution] Whether to interpret the contents of an ignore file relative to the config file or the ignore file.
|
||||
* - gitignoreResolution: false (default): Interprets ignore patterns relative to the config file
|
||||
* - gitignoreResolution: true: Interprets the ignore patterns in a file relative to the ignore file
|
||||
* @property {string} [name] The name to give the output config object(s).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for `includeIgnoreFile()`. May be provided as an object or, for
|
||||
* legacy compatibility with `@eslint/compat`, as a string which is treated as
|
||||
* the `name` option.
|
||||
* @typedef {IncludeIgnoreFileOptionsObject | string} IncludeIgnoreFileOptions
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Converts an ESLint ignore pattern to a minimatch pattern.
|
||||
* @param {string} pattern The .eslintignore or .gitignore pattern to convert.
|
||||
* @returns {string} The converted pattern.
|
||||
*/
|
||||
function convertIgnorePatternToMinimatch(pattern) {
|
||||
const isNegated = pattern.startsWith("!");
|
||||
const negatedPrefix = isNegated ? "!" : "";
|
||||
const patternToTest = (isNegated ? pattern.slice(1) : pattern).trimEnd();
|
||||
|
||||
// special cases
|
||||
if (["", "**", "/**", "**/"].includes(patternToTest)) {
|
||||
return `${negatedPrefix}${patternToTest}`;
|
||||
}
|
||||
|
||||
const firstIndexOfSlash = patternToTest.indexOf("/");
|
||||
|
||||
const matchEverywherePrefix =
|
||||
firstIndexOfSlash < 0 || firstIndexOfSlash === patternToTest.length - 1
|
||||
? "**/"
|
||||
: "";
|
||||
|
||||
const patternWithoutLeadingSlash =
|
||||
firstIndexOfSlash === 0 ? patternToTest.slice(1) : patternToTest;
|
||||
|
||||
/*
|
||||
* Escape `{` and `(` because in gitignore patterns they are just
|
||||
* literal characters without any specific syntactic meaning,
|
||||
* while in minimatch patterns they can form brace expansion or extglob syntax.
|
||||
*
|
||||
* For example, gitignore pattern `src/{a,b}.js` ignores file `src/{a,b}.js`.
|
||||
* But, the same minimatch pattern `src/{a,b}.js` ignores files `src/a.js` and `src/b.js`.
|
||||
* Minimatch pattern `src/\{a,b}.js` is equivalent to gitignore pattern `src/{a,b}.js`.
|
||||
*/
|
||||
const escapedPatternWithoutLeadingSlash =
|
||||
patternWithoutLeadingSlash.replaceAll(
|
||||
// eslint-disable-next-line regexp/no-empty-lookarounds-assertion -- False positive
|
||||
/(?=((?:\\.|[^{(])*))\1([{(])/guy,
|
||||
"$1\\$2",
|
||||
);
|
||||
|
||||
const matchInsideSuffix = patternToTest.endsWith("/**") ? "/*" : "";
|
||||
|
||||
return `${negatedPrefix}${matchEverywherePrefix}${escapedPatternWithoutLeadingSlash}${matchInsideSuffix}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} ignoreFilePath
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function ignoreFilePathToPatterns(ignoreFilePath) {
|
||||
const ignoreFile = fs.readFileSync(ignoreFilePath, "utf8");
|
||||
const lines = ignoreFile.split(/\r?\n/u);
|
||||
|
||||
return lines
|
||||
.map(line => line.trim())
|
||||
.filter(line => line && !line.startsWith("#"))
|
||||
.map(convertIgnorePatternToMinimatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to parse and validate the options to `includeIgnoreFile()`
|
||||
*
|
||||
* @param {string | { gitignoreResolution?: unknown, name?: unknown } | undefined} options
|
||||
* @returns {{ gitignoreResolution: boolean, name: string }}
|
||||
*/
|
||||
function parseOptions(options) {
|
||||
// legacy compatibility with @eslint/compat's `includeIgnoreFile`
|
||||
if (typeof options === "string") {
|
||||
return { gitignoreResolution: false, name: options };
|
||||
}
|
||||
|
||||
const optionsObject = options ?? {};
|
||||
if (typeof optionsObject !== "object" || Array.isArray(optionsObject)) {
|
||||
throw new TypeError(
|
||||
"The options argument to `includeIgnoreFile()` should be an object or a string.",
|
||||
);
|
||||
}
|
||||
|
||||
const gitignoreResolution = optionsObject.gitignoreResolution ?? false;
|
||||
if (typeof gitignoreResolution !== "boolean") {
|
||||
throw new TypeError(
|
||||
"The `gitignoreResolution` option must be specified a boolean or omitted",
|
||||
);
|
||||
}
|
||||
|
||||
const name = optionsObject.name ?? `Imported .gitignore patterns`;
|
||||
if (typeof name !== "string") {
|
||||
throw new TypeError(
|
||||
"The `name` option must be specified as a string or omitted.",
|
||||
);
|
||||
}
|
||||
|
||||
return { gitignoreResolution, name };
|
||||
}
|
||||
|
||||
/**
|
||||
* @overload
|
||||
*
|
||||
* Reads ignore files and returns objects with the ignore patterns.
|
||||
*
|
||||
* @param {string[]} ignoreFilePathArg The paths of ignore files to include.
|
||||
* @param {IncludeIgnoreFileOptions} [options]
|
||||
* @returns {ConfigObject[]}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @overload
|
||||
*
|
||||
* Reads an ignore file and returns an object with the ignore patterns.
|
||||
*
|
||||
* @param {string} ignoreFilePathArg The path of the ignore file to include.
|
||||
* @param {IncludeIgnoreFileOptions} [options]
|
||||
* @returns {ConfigObject}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @overload
|
||||
*
|
||||
* Reads an ignore file(s) and returns an object(s) with the ignore patterns.
|
||||
*
|
||||
* @param {string[] | string} ignoreFilePathArg The path(s) of the ignore file(s) to include.
|
||||
* @param {IncludeIgnoreFileOptions} [options]
|
||||
* @returns {ConfigObject[] | ConfigObject}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reads an ignore file(s) and returns an object(s) with the ignore patterns.
|
||||
*
|
||||
* @param {string[] | string} ignoreFilePathArg The path(s) of the ignore file(s) to include.
|
||||
* @param {IncludeIgnoreFileOptions} [options]
|
||||
* @returns {ConfigObject[] | ConfigObject}
|
||||
*/
|
||||
function includeIgnoreFile(ignoreFilePathArg, options) {
|
||||
const returnSingleObject = !Array.isArray(ignoreFilePathArg);
|
||||
const ignoreFilePaths = Array.isArray(ignoreFilePathArg)
|
||||
? ignoreFilePathArg
|
||||
: [ignoreFilePathArg];
|
||||
for (const ignorePath of ignoreFilePaths) {
|
||||
if (typeof ignorePath !== "string") {
|
||||
throw new TypeError(
|
||||
"The first argument to `includeIgnoreFile()` should be a string or array of strings",
|
||||
);
|
||||
}
|
||||
if (!path.isAbsolute(ignorePath)) {
|
||||
throw new Error(
|
||||
`The ignore file location must be an absolute path. Received ${ignorePath}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const { gitignoreResolution, name } = parseOptions(options);
|
||||
|
||||
if (returnSingleObject) {
|
||||
return {
|
||||
name,
|
||||
ignores: ignoreFilePathToPatterns(ignoreFilePathArg),
|
||||
...(gitignoreResolution
|
||||
? { basePath: path.dirname(ignoreFilePathArg) }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
return ignoreFilePaths.map((ignoreFilePath, i) => ({
|
||||
name: `${name} (${i})`,
|
||||
ignores: ignoreFilePathToPatterns(ignoreFilePath),
|
||||
...(gitignoreResolution
|
||||
? { basePath: path.dirname(ignoreFilePath) }
|
||||
: {}),
|
||||
}));
|
||||
}
|
||||
|
||||
export { convertIgnorePatternToMinimatch, defineConfig, globalIgnores, includeIgnoreFile };
|
||||
@@ -0,0 +1,694 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("_values", () => {
|
||||
expect(z.string()._zod.values).toEqual(undefined);
|
||||
expect(z.enum(["a", "b"])._zod.values).toEqual(new Set(["a", "b"]));
|
||||
expect(z.nativeEnum({ a: "A", b: "B" })._zod.values).toEqual(new Set(["A", "B"]));
|
||||
expect(z.literal("test")._zod.values).toEqual(new Set(["test"]));
|
||||
expect(z.literal(123)._zod.values).toEqual(new Set([123]));
|
||||
expect(z.literal(true)._zod.values).toEqual(new Set([true]));
|
||||
expect(z.literal(BigInt(123))._zod.values).toEqual(new Set([BigInt(123)]));
|
||||
expect(z.undefined()._zod.values).toEqual(new Set([undefined]));
|
||||
expect(z.null()._zod.values).toEqual(new Set([null]));
|
||||
|
||||
const t = z.literal("test");
|
||||
expect(t.optional()._zod.values).toEqual(new Set(["test", undefined]));
|
||||
expect(t.nullable()._zod.values).toEqual(new Set(["test", null]));
|
||||
expect(t.default("test")._zod.values).toEqual(new Set(["test"]));
|
||||
expect(t.catch("test")._zod.values).toEqual(new Set(["test"]));
|
||||
|
||||
const pre = z.preprocess((val) => String(val), z.string()).pipe(z.literal("test"));
|
||||
expect(pre._zod.values).toEqual(undefined);
|
||||
|
||||
const post = z.literal("test").transform((_) => Math.random());
|
||||
expect(post._zod.values).toEqual(new Set(["test"]));
|
||||
|
||||
// Test that readonly literals pass through their values property
|
||||
expect(z.literal("test").readonly()._zod.values).toEqual(new Set(["test"]));
|
||||
});
|
||||
|
||||
test("valid parse - object", () => {
|
||||
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 - include discriminator key (deprecated)", () => {
|
||||
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 - optional discriminator (object)", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a").optional(), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
]);
|
||||
expect(schema.parse({ type: "a", a: "abc" })).toEqual({ type: "a", a: "abc" });
|
||||
expect(schema.parse({ a: "abc" })).toEqual({ a: "abc" });
|
||||
});
|
||||
|
||||
test("valid - discriminator value of various primitive types", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("1"), val: z.string() }),
|
||||
z.object({ type: z.literal(1), val: z.string() }),
|
||||
z.object({ type: z.literal(BigInt(1)), val: z.string() }),
|
||||
z.object({ type: z.literal("true"), val: z.string() }),
|
||||
z.object({ type: z.literal(true), val: z.string() }),
|
||||
z.object({ type: z.literal("null"), val: z.string() }),
|
||||
z.object({ type: z.null(), val: z.string() }),
|
||||
z.object({ type: z.literal("undefined"), val: z.string() }),
|
||||
z.object({ type: z.undefined(), val: z.string() }),
|
||||
]);
|
||||
|
||||
expect(schema.parse({ type: "1", val: "val" })).toEqual({ type: "1", val: "val" });
|
||||
expect(schema.parse({ type: 1, val: "val" })).toEqual({ type: 1, val: "val" });
|
||||
expect(schema.parse({ type: BigInt(1), val: "val" })).toEqual({
|
||||
type: BigInt(1),
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "true", val: "val" })).toEqual({
|
||||
type: "true",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: true, val: "val" })).toEqual({
|
||||
type: true,
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "null", val: "val" })).toEqual({
|
||||
type: "null",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: null, val: "val" })).toEqual({
|
||||
type: null,
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "undefined", val: "val" })).toEqual({
|
||||
type: "undefined",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: undefined, val: "val" })).toEqual({
|
||||
type: undefined,
|
||||
val: "val",
|
||||
});
|
||||
|
||||
const fail = schema.safeParse({
|
||||
type: "not_a_key",
|
||||
val: "val",
|
||||
});
|
||||
expect(fail.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
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) {
|
||||
// [
|
||||
// {
|
||||
// code: z.ZodIssueCode.invalid_type,
|
||||
// expected: z.ZodParsedType.object,
|
||||
// input: null,
|
||||
// message: "Expected object, received null",
|
||||
// received: z.ZodParsedType.null,
|
||||
// path: [],
|
||||
// },
|
||||
// ];
|
||||
expect(e.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "object",
|
||||
"message": "Invalid input: expected object, received null",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("invalid discriminator value", () => {
|
||||
const result = z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.safeParse({ type: "x", a: "abc" });
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [],
|
||||
"note": "No matching discriminator",
|
||||
"discriminator": "type",
|
||||
"options": [
|
||||
"a",
|
||||
"b"
|
||||
],
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid discriminator value. Expected 'a' | 'b'"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("invalid discriminator value - unionFallback", () => {
|
||||
const result = z
|
||||
.discriminatedUnion(
|
||||
"type",
|
||||
[z.object({ type: z.literal("a"), a: z.string() }), z.object({ type: z.literal("b"), b: z.string() })],
|
||||
{ unionFallback: true }
|
||||
)
|
||||
.safeParse({ type: "x", a: "abc" });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [
|
||||
[
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"a"
|
||||
],
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid input: expected \\"a\\""
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"b"
|
||||
],
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid input: expected \\"b\\""
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"b"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("valid discriminator value, invalid data", () => {
|
||||
const result = z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.safeParse({ type: "a", b: "abc" });
|
||||
|
||||
// [
|
||||
// {
|
||||
// code: z.ZodIssueCode.invalid_type,
|
||||
// expected: z.ZodParsedType.string,
|
||||
// message: "Required",
|
||||
// path: ["a"],
|
||||
// received: z.ZodParsedType.undefined,
|
||||
// },
|
||||
// ];
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"a"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("wrong schema - missing discriminator", () => {
|
||||
// @ts-expect-error missing discriminator property
|
||||
z.discriminatedUnion("type", [z.object({ value: z.string() })]);
|
||||
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ b: z.string() }) as any,
|
||||
])._zod.propValues;
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(e.message.includes("Invalid discriminated union option")).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
// removed to account for unions of unions
|
||||
// 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("Duplicate discriminator value")).toEqual(true);
|
||||
// }
|
||||
// });
|
||||
|
||||
test("async - valid", async () => {
|
||||
const schema = 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(),
|
||||
}),
|
||||
]);
|
||||
const data = { type: "a", a: "1" };
|
||||
const result = await schema.safeParseAsync(data);
|
||||
expect(result.data).toEqual({ type: "a", a: 1 });
|
||||
});
|
||||
|
||||
test("async - invalid", async () => {
|
||||
// try {
|
||||
const a = 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(),
|
||||
}),
|
||||
]);
|
||||
const result = await a.safeParseAsync({ type: "a", a: 1 });
|
||||
|
||||
// expect(JSON.parse(e.message)).toEqual([
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "string",
|
||||
// input: 1,
|
||||
// received: "number",
|
||||
// path: ["a"],
|
||||
// message: "Expected string, received number",
|
||||
// },
|
||||
// ]);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"a"
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("valid - literals with .default or .pipe", () => {
|
||||
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.literal("bar").transform((val) => val),
|
||||
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>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key: "a" } | { key: "b" | "c" } | { key: MyEnum.d | MyEnum.e }>();
|
||||
|
||||
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<"asdfasdf">(),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key: "a" } | { key: "b" & z.core.$brand<"asdfasdf"> }>();
|
||||
|
||||
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>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key?: "a" | undefined; a: true } | { key: "b" | null; b: 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("multiple discriminators", () => {
|
||||
const FreeConfig = z.object({
|
||||
type: z.literal("free"),
|
||||
min_cents: z.null(),
|
||||
});
|
||||
|
||||
// console.log(FreeConfig.shape.type);
|
||||
const PricedConfig = z.object({
|
||||
type: z.literal("fiat-price"),
|
||||
// min_cents: z.int().nullable(),
|
||||
min_cents: z.null(),
|
||||
});
|
||||
|
||||
const Config = z.discriminatedUnion("type", [FreeConfig, PricedConfig]);
|
||||
|
||||
Config.parse({
|
||||
min_cents: null,
|
||||
type: "fiat-price",
|
||||
name: "Standard",
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
Config.parse({
|
||||
min_cents: null,
|
||||
type: "not real",
|
||||
name: "Standard",
|
||||
});
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("single element union", () => {
|
||||
const schema = z.object({
|
||||
a: z.literal("discKey"),
|
||||
b: z.enum(["apple", "banana"]),
|
||||
c: z.object({ id: z.string() }),
|
||||
});
|
||||
|
||||
const input = {
|
||||
a: "discKey",
|
||||
b: "apple",
|
||||
c: {}, // Invalid, as schema requires `id` property
|
||||
};
|
||||
|
||||
// Validation must fail here, but it doesn't
|
||||
|
||||
const u = z.discriminatedUnion("a", [schema]);
|
||||
const result = u.safeParse(input);
|
||||
expect(result).toMatchObject({ success: false });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"c",
|
||||
"id"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(u.options.length).toEqual(1);
|
||||
});
|
||||
|
||||
test("nested discriminated unions", () => {
|
||||
const BaseError = z.object({ status: z.literal("failed"), message: z.string() });
|
||||
const MyErrors = z.discriminatedUnion("code", [
|
||||
BaseError.extend({ code: z.literal(400) }),
|
||||
BaseError.extend({ code: z.literal(401) }),
|
||||
BaseError.extend({ code: z.literal(500) }),
|
||||
]);
|
||||
|
||||
const MyResult = z.discriminatedUnion("status", [
|
||||
z.object({ status: z.literal("success"), data: z.string() }),
|
||||
MyErrors,
|
||||
]);
|
||||
|
||||
expect(MyErrors._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": Set {
|
||||
400,
|
||||
401,
|
||||
500,
|
||||
},
|
||||
"status": Set {
|
||||
"failed",
|
||||
},
|
||||
}
|
||||
`);
|
||||
expect(MyResult._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": Set {
|
||||
400,
|
||||
401,
|
||||
500,
|
||||
},
|
||||
"status": Set {
|
||||
"success",
|
||||
"failed",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
||||
const result = MyResult.parse({ status: "success", data: "hello" });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "hello",
|
||||
"status": "success",
|
||||
}
|
||||
`);
|
||||
const result2 = MyResult.parse({ status: "failed", code: 400, message: "bad request" });
|
||||
expect(result2).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 400,
|
||||
"message": "bad request",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
const result3 = MyResult.parse({ status: "failed", code: 401, message: "unauthorized" });
|
||||
expect(result3).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 401,
|
||||
"message": "unauthorized",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
const result4 = MyResult.parse({ status: "failed", code: 500, message: "internal server error" });
|
||||
expect(result4).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 500,
|
||||
"message": "internal server error",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("readonly literal discriminator", () => {
|
||||
const discUnion = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a").readonly(), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.number() }),
|
||||
]);
|
||||
|
||||
// Test that both discriminator values are correctly included in propValues
|
||||
const propValues = discUnion._zod.propValues;
|
||||
expect(propValues?.type?.has("a")).toBe(true);
|
||||
expect(propValues?.type?.has("b")).toBe(true);
|
||||
|
||||
// Test that the discriminated union works correctly
|
||||
const result1 = discUnion.parse({ type: "a", a: "hello" });
|
||||
expect(result1).toEqual({ type: "a", a: "hello" });
|
||||
|
||||
const result2 = discUnion.parse({ type: "b", b: 42 });
|
||||
expect(result2).toEqual({ type: "b", b: 42 });
|
||||
|
||||
// Test that invalid discriminator values are rejected
|
||||
expect(() => {
|
||||
discUnion.parse({ type: "c", a: "hello" });
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("pipes", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
type: z.literal("foo"),
|
||||
})
|
||||
.transform((s) => ({ ...s, v: 2 }));
|
||||
|
||||
expect(schema._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"type": Set {
|
||||
"foo",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
||||
const schema2 = z.object({
|
||||
type: z.literal("bar"),
|
||||
});
|
||||
|
||||
const combinedSchema = z.discriminatedUnion("type", [schema, schema2], {
|
||||
unionFallback: false,
|
||||
});
|
||||
|
||||
combinedSchema.parse({
|
||||
type: "foo",
|
||||
v: 2,
|
||||
});
|
||||
});
|
||||
|
||||
test("def", () => {
|
||||
const schema = z.discriminatedUnion(
|
||||
"type",
|
||||
[z.object({ type: z.literal("play") }), z.object({ type: z.literal("pause") })],
|
||||
{ unionFallback: true }
|
||||
);
|
||||
|
||||
expect(schema.def).toBeDefined();
|
||||
expect(schema.def.discriminator).toEqual("type");
|
||||
expect(schema.def.unionFallback).toEqual(true);
|
||||
});
|
||||
|
||||
test("encode with codec discriminator", () => {
|
||||
const codec1 = z.codec(z.literal(1), z.literal("one"), {
|
||||
decode: () => "one" as const,
|
||||
encode: () => 1 as const,
|
||||
});
|
||||
|
||||
const codec2 = z.codec(z.literal(2), z.literal("two"), {
|
||||
decode: () => "two" as const,
|
||||
encode: () => 2 as const,
|
||||
});
|
||||
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: codec1, value: z.string() }),
|
||||
z.object({ type: codec2, value: z.number() }),
|
||||
]);
|
||||
|
||||
// decode (forward) should work
|
||||
const decoded = schema.decode({ type: 1, value: "hello" });
|
||||
expect(decoded).toEqual({ type: "one", value: "hello" });
|
||||
|
||||
// encode (backward) should also work — the discriminator values differ
|
||||
// between forward (1, 2) and backward ("one", "two") directions
|
||||
const encoded = z.encode(schema, { type: "one", value: "hello" });
|
||||
expect(encoded).toEqual({ type: 1, value: "hello" });
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
var p=Object.defineProperty;var t=(o,r)=>p(o,"name",{value:r,configurable:!0});import a from"node:repl";import{v as l}from"./package-B13bX4zz.mjs";import{t as c}from"./index-DQtFPMc2.mjs";import"node:path";import"node:url";import"esbuild";import"node:crypto";import"./node-features-JeyyvQz6.mjs";import"node:fs";import"node:os";import"./temporary-directory-BDDVQOvU.mjs";console.log(`Welcome to tsx v${l} (Node.js ${process.version}).
|
||||
Type ".help" for more information.`);const s=a.start(),{eval:f}=s,v=t(async function(o,r,e,i){const m=await c(o,e,{loader:"ts",tsconfigRaw:{compilerOptions:{preserveValueImports:!0}},define:{require:"global.require"}}).catch(n=>(console.log(n.message),{code:`
|
||||
`}));return f.call(this,m.code,r,e,i)},"preEval");s.eval=v;
|
||||
@@ -0,0 +1,295 @@
|
||||
{
|
||||
"name": "@noble/curves",
|
||||
"version": "1.9.7",
|
||||
"description": "Audited & minimal JS implementation of elliptic curve cryptography",
|
||||
"files": [
|
||||
"*.js",
|
||||
"*.js.map",
|
||||
"*.d.ts",
|
||||
"*.d.ts.map",
|
||||
"esm",
|
||||
"src",
|
||||
"abstract",
|
||||
"!oprf.*",
|
||||
"!webcrypto.*"
|
||||
],
|
||||
"scripts": {
|
||||
"bench": "npm run bench:install; cd test/benchmark; node secp256k1.js; node curves.js; node utils.js; node bls.js",
|
||||
"bench:install": "cd test/benchmark; npm install; npm install ../.. --install-links",
|
||||
"build": "tsc && tsc -p tsconfig.cjs.json",
|
||||
"build:release": "npx jsbt esbuild test/build",
|
||||
"build:clean": "rm {.,esm,abstract,esm/abstract}/*.{js,d.ts,d.ts.map,js.map} 2> /dev/null",
|
||||
"lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'",
|
||||
"format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'",
|
||||
"test": "node --disable-warning=ExperimentalWarning test/index.js",
|
||||
"test:bun": "bun test/index.js",
|
||||
"test:deno": "deno --allow-env --allow-read test/index.js",
|
||||
"test:coverage": "npm install --no-save c8@10.1.2 && npx c8 npm test"
|
||||
},
|
||||
"author": "Paul Miller (https://paulmillr.com)",
|
||||
"homepage": "https://paulmillr.com/noble/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/paulmillr/noble-curves.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@paulmillr/jsbt": "0.4.0",
|
||||
"@types/node": "22.15.21",
|
||||
"fast-check": "4.1.1",
|
||||
"micro-bmark": "0.4.2",
|
||||
"micro-should": "0.5.3",
|
||||
"prettier": "3.5.3",
|
||||
"typescript": "5.8.3"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"main": "index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./esm/index.js",
|
||||
"require": "./index.js"
|
||||
},
|
||||
"./abstract/bls": {
|
||||
"import": "./esm/abstract/bls.js",
|
||||
"require": "./abstract/bls.js"
|
||||
},
|
||||
"./abstract/curve": {
|
||||
"import": "./esm/abstract/curve.js",
|
||||
"require": "./abstract/curve.js"
|
||||
},
|
||||
"./abstract/edwards": {
|
||||
"import": "./esm/abstract/edwards.js",
|
||||
"require": "./abstract/edwards.js"
|
||||
},
|
||||
"./abstract/hash-to-curve": {
|
||||
"import": "./esm/abstract/hash-to-curve.js",
|
||||
"require": "./abstract/hash-to-curve.js"
|
||||
},
|
||||
"./abstract/modular": {
|
||||
"import": "./esm/abstract/modular.js",
|
||||
"require": "./abstract/modular.js"
|
||||
},
|
||||
"./abstract/montgomery": {
|
||||
"import": "./esm/abstract/montgomery.js",
|
||||
"require": "./abstract/montgomery.js"
|
||||
},
|
||||
"./abstract/poseidon": {
|
||||
"import": "./esm/abstract/poseidon.js",
|
||||
"require": "./abstract/poseidon.js"
|
||||
},
|
||||
"./abstract/tower": {
|
||||
"import": "./esm/abstract/tower.js",
|
||||
"require": "./abstract/tower.js"
|
||||
},
|
||||
"./abstract/utils": {
|
||||
"import": "./esm/abstract/utils.js",
|
||||
"require": "./abstract/utils.js"
|
||||
},
|
||||
"./abstract/weierstrass": {
|
||||
"import": "./esm/abstract/weierstrass.js",
|
||||
"require": "./abstract/weierstrass.js"
|
||||
},
|
||||
"./abstract/fft": {
|
||||
"import": "./esm/abstract/fft.js",
|
||||
"require": "./abstract/fft.js"
|
||||
},
|
||||
"./_shortw_utils": {
|
||||
"import": "./esm/_shortw_utils.js",
|
||||
"require": "./_shortw_utils.js"
|
||||
},
|
||||
"./bls12-381": {
|
||||
"import": "./esm/bls12-381.js",
|
||||
"require": "./bls12-381.js"
|
||||
},
|
||||
"./bn254": {
|
||||
"import": "./esm/bn254.js",
|
||||
"require": "./bn254.js"
|
||||
},
|
||||
"./ed448": {
|
||||
"import": "./esm/ed448.js",
|
||||
"require": "./ed448.js"
|
||||
},
|
||||
"./ed25519": {
|
||||
"import": "./esm/ed25519.js",
|
||||
"require": "./ed25519.js"
|
||||
},
|
||||
"./index": {
|
||||
"import": "./esm/index.js",
|
||||
"require": "./index.js"
|
||||
},
|
||||
"./jubjub": {
|
||||
"import": "./esm/jubjub.js",
|
||||
"require": "./jubjub.js"
|
||||
},
|
||||
"./misc": {
|
||||
"import": "./esm/misc.js",
|
||||
"require": "./misc.js"
|
||||
},
|
||||
"./nist": {
|
||||
"import": "./esm/nist.js",
|
||||
"require": "./nist.js"
|
||||
},
|
||||
"./p256": {
|
||||
"import": "./esm/p256.js",
|
||||
"require": "./p256.js"
|
||||
},
|
||||
"./p384": {
|
||||
"import": "./esm/p384.js",
|
||||
"require": "./p384.js"
|
||||
},
|
||||
"./p521": {
|
||||
"import": "./esm/p521.js",
|
||||
"require": "./p521.js"
|
||||
},
|
||||
"./pasta": {
|
||||
"import": "./esm/pasta.js",
|
||||
"require": "./pasta.js"
|
||||
},
|
||||
"./secp256k1": {
|
||||
"import": "./esm/secp256k1.js",
|
||||
"require": "./secp256k1.js"
|
||||
},
|
||||
"./utils": {
|
||||
"import": "./esm/utils.js",
|
||||
"require": "./utils.js"
|
||||
},
|
||||
"./abstract/bls.js": {
|
||||
"import": "./esm/abstract/bls.js",
|
||||
"require": "./abstract/bls.js"
|
||||
},
|
||||
"./abstract/curve.js": {
|
||||
"import": "./esm/abstract/curve.js",
|
||||
"require": "./abstract/curve.js"
|
||||
},
|
||||
"./abstract/edwards.js": {
|
||||
"import": "./esm/abstract/edwards.js",
|
||||
"require": "./abstract/edwards.js"
|
||||
},
|
||||
"./abstract/hash-to-curve.js": {
|
||||
"import": "./esm/abstract/hash-to-curve.js",
|
||||
"require": "./abstract/hash-to-curve.js"
|
||||
},
|
||||
"./abstract/modular.js": {
|
||||
"import": "./esm/abstract/modular.js",
|
||||
"require": "./abstract/modular.js"
|
||||
},
|
||||
"./abstract/montgomery.js": {
|
||||
"import": "./esm/abstract/montgomery.js",
|
||||
"require": "./abstract/montgomery.js"
|
||||
},
|
||||
"./abstract/poseidon.js": {
|
||||
"import": "./esm/abstract/poseidon.js",
|
||||
"require": "./abstract/poseidon.js"
|
||||
},
|
||||
"./abstract/tower.js": {
|
||||
"import": "./esm/abstract/tower.js",
|
||||
"require": "./abstract/tower.js"
|
||||
},
|
||||
"./abstract/utils.js": {
|
||||
"import": "./esm/abstract/utils.js",
|
||||
"require": "./abstract/utils.js"
|
||||
},
|
||||
"./abstract/weierstrass.js": {
|
||||
"import": "./esm/abstract/weierstrass.js",
|
||||
"require": "./abstract/weierstrass.js"
|
||||
},
|
||||
"./abstract/fft.js": {
|
||||
"import": "./esm/abstract/fft.js",
|
||||
"require": "./abstract/fft.js"
|
||||
},
|
||||
"./_shortw_utils.js": {
|
||||
"import": "./esm/_shortw_utils.js",
|
||||
"require": "./_shortw_utils.js"
|
||||
},
|
||||
"./bls12-381.js": {
|
||||
"import": "./esm/bls12-381.js",
|
||||
"require": "./bls12-381.js"
|
||||
},
|
||||
"./bn254.js": {
|
||||
"import": "./esm/bn254.js",
|
||||
"require": "./bn254.js"
|
||||
},
|
||||
"./utils.js": {
|
||||
"import": "./esm/utils.js",
|
||||
"require": "./utils.js"
|
||||
},
|
||||
"./ed448.js": {
|
||||
"import": "./esm/ed448.js",
|
||||
"require": "./ed448.js"
|
||||
},
|
||||
"./ed25519.js": {
|
||||
"import": "./esm/ed25519.js",
|
||||
"require": "./ed25519.js"
|
||||
},
|
||||
"./index.js": {
|
||||
"import": "./esm/index.js",
|
||||
"require": "./index.js"
|
||||
},
|
||||
"./jubjub.js": {
|
||||
"import": "./esm/jubjub.js",
|
||||
"require": "./jubjub.js"
|
||||
},
|
||||
"./misc.js": {
|
||||
"import": "./esm/misc.js",
|
||||
"require": "./misc.js"
|
||||
},
|
||||
"./nist.js": {
|
||||
"import": "./esm/nist.js",
|
||||
"require": "./nist.js"
|
||||
},
|
||||
"./p256.js": {
|
||||
"import": "./esm/p256.js",
|
||||
"require": "./p256.js"
|
||||
},
|
||||
"./p384.js": {
|
||||
"import": "./esm/p384.js",
|
||||
"require": "./p384.js"
|
||||
},
|
||||
"./p521.js": {
|
||||
"import": "./esm/p521.js",
|
||||
"require": "./p521.js"
|
||||
},
|
||||
"./pasta.js": {
|
||||
"import": "./esm/pasta.js",
|
||||
"require": "./pasta.js"
|
||||
},
|
||||
"./secp256k1.js": {
|
||||
"import": "./esm/secp256k1.js",
|
||||
"require": "./secp256k1.js"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.21.3 || >=16"
|
||||
},
|
||||
"keywords": [
|
||||
"elliptic",
|
||||
"curve",
|
||||
"cryptography",
|
||||
"secp256k1",
|
||||
"ed25519",
|
||||
"p256",
|
||||
"p384",
|
||||
"p521",
|
||||
"secp256r1",
|
||||
"ed448",
|
||||
"x25519",
|
||||
"ed25519",
|
||||
"bls12-381",
|
||||
"bn254",
|
||||
"alt_bn128",
|
||||
"bls",
|
||||
"noble",
|
||||
"ecc",
|
||||
"ecdsa",
|
||||
"eddsa",
|
||||
"weierstrass",
|
||||
"montgomery",
|
||||
"edwards",
|
||||
"schnorr",
|
||||
"fft"
|
||||
],
|
||||
"funding": "https://paulmillr.com/funding/"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
var getPrototypeOf = require("./getPrototypeOf.js");
|
||||
var isNativeReflectConstruct = require("./isNativeReflectConstruct.js");
|
||||
var possibleConstructorReturn = require("./possibleConstructorReturn.js");
|
||||
function _callSuper(t, o, e) {
|
||||
return o = getPrototypeOf(o), possibleConstructorReturn(t, isNativeReflectConstruct() ? Reflect.construct(o, e || [], getPrototypeOf(t).constructor) : o.apply(t, e));
|
||||
}
|
||||
module.exports = _callSuper, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2020_date = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
const es2020_intl_1 = require("./es2020.intl");
|
||||
exports.es2020_date = {
|
||||
libs: [es2020_intl_1.es2020_intl],
|
||||
variables: [['Date', base_config_1.TYPE]],
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getStringLength = getStringLength;
|
||||
let segmenter;
|
||||
function isASCII(value) {
|
||||
return /^[\u0020-\u007f]*$/u.test(value);
|
||||
}
|
||||
function getStringLength(value) {
|
||||
if (isASCII(value)) {
|
||||
return value.length;
|
||||
}
|
||||
segmenter ??= new Intl.Segmenter();
|
||||
return [...segmenter.segment(value)].length;
|
||||
}
|
||||
@@ -0,0 +1,655 @@
|
||||
(function () { 'use strict';
|
||||
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
// See LICENSE.md for more information.
|
||||
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
|
||||
/**
|
||||
* @param {number} a The number to test.
|
||||
* @param {number} min The minimum value in the range, inclusive.
|
||||
* @param {number} max The maximum value in the range, inclusive.
|
||||
* @return {boolean} True if a >= min and a <= max.
|
||||
*/
|
||||
function inRange(a, min, max) {
|
||||
return min <= a && a <= max;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} o
|
||||
* @return {Object}
|
||||
*/
|
||||
function ToDictionary(o) {
|
||||
if (o === undefined) return {};
|
||||
if (o === Object(o)) return o;
|
||||
throw TypeError('Could not convert argument to dictionary');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} string Input string of UTF-16 code units.
|
||||
* @return {!Array.<number>} Code points.
|
||||
*/
|
||||
function stringToCodePoints(string) {
|
||||
// https://heycam.github.io/webidl/#dfn-obtain-unicode
|
||||
|
||||
// 1. Let S be the DOMString value.
|
||||
var s = String(string);
|
||||
|
||||
// 2. Let n be the length of S.
|
||||
var n = s.length;
|
||||
|
||||
// 3. Initialize i to 0.
|
||||
var i = 0;
|
||||
|
||||
// 4. Initialize U to be an empty sequence of Unicode characters.
|
||||
var u = [];
|
||||
|
||||
// 5. While i < n:
|
||||
while (i < n) {
|
||||
|
||||
// 1. Let c be the code unit in S at index i.
|
||||
var c = s.charCodeAt(i);
|
||||
|
||||
// 2. Depending on the value of c:
|
||||
|
||||
// c < 0xD800 or c > 0xDFFF
|
||||
if (c < 0xD800 || c > 0xDFFF) {
|
||||
// Append to U the Unicode character with code point c.
|
||||
u.push(c);
|
||||
}
|
||||
|
||||
// 0xDC00 ≤ c ≤ 0xDFFF
|
||||
else if (0xDC00 <= c && c <= 0xDFFF) {
|
||||
// Append to U a U+FFFD REPLACEMENT CHARACTER.
|
||||
u.push(0xFFFD);
|
||||
}
|
||||
|
||||
// 0xD800 ≤ c ≤ 0xDBFF
|
||||
else if (0xD800 <= c && c <= 0xDBFF) {
|
||||
// 1. If i = n−1, then append to U a U+FFFD REPLACEMENT
|
||||
// CHARACTER.
|
||||
if (i === n - 1) {
|
||||
u.push(0xFFFD);
|
||||
}
|
||||
// 2. Otherwise, i < n−1:
|
||||
else {
|
||||
// 1. Let d be the code unit in S at index i+1.
|
||||
var d = string.charCodeAt(i + 1);
|
||||
|
||||
// 2. If 0xDC00 ≤ d ≤ 0xDFFF, then:
|
||||
if (0xDC00 <= d && d <= 0xDFFF) {
|
||||
// 1. Let a be c & 0x3FF.
|
||||
var a = c & 0x3FF;
|
||||
|
||||
// 2. Let b be d & 0x3FF.
|
||||
var b = d & 0x3FF;
|
||||
|
||||
// 3. Append to U the Unicode character with code point
|
||||
// 2^16+2^10*a+b.
|
||||
u.push(0x10000 + (a << 10) + b);
|
||||
|
||||
// 4. Set i to i+1.
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a
|
||||
// U+FFFD REPLACEMENT CHARACTER.
|
||||
else {
|
||||
u.push(0xFFFD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Set i to i+1.
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// 6. Return U.
|
||||
return u;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Array.<number>} code_points Array of code points.
|
||||
* @return {string} string String of UTF-16 code units.
|
||||
*/
|
||||
function codePointsToString(code_points) {
|
||||
var s = '';
|
||||
for (var i = 0; i < code_points.length; ++i) {
|
||||
var cp = code_points[i];
|
||||
if (cp <= 0xFFFF) {
|
||||
s += String.fromCharCode(cp);
|
||||
} else {
|
||||
cp -= 0x10000;
|
||||
s += String.fromCharCode((cp >> 10) + 0xD800,
|
||||
(cp & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implementation of Encoding specification
|
||||
// https://encoding.spec.whatwg.org/
|
||||
//
|
||||
|
||||
//
|
||||
// 3. Terminology
|
||||
//
|
||||
|
||||
/**
|
||||
* End-of-stream is a special token that signifies no more tokens
|
||||
* are in the stream.
|
||||
* @const
|
||||
*/ var end_of_stream = -1;
|
||||
|
||||
/**
|
||||
* A stream represents an ordered sequence of tokens.
|
||||
*
|
||||
* @constructor
|
||||
* @param {!(Array.<number>|Uint8Array)} tokens Array of tokens that provide the
|
||||
* stream.
|
||||
*/
|
||||
function Stream(tokens) {
|
||||
/** @type {!Array.<number>} */
|
||||
this.tokens = [].slice.call(tokens);
|
||||
}
|
||||
|
||||
Stream.prototype = {
|
||||
/**
|
||||
* @return {boolean} True if end-of-stream has been hit.
|
||||
*/
|
||||
endOfStream: function() {
|
||||
return !this.tokens.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* When a token is read from a stream, the first token in the
|
||||
* stream must be returned and subsequently removed, and
|
||||
* end-of-stream must be returned otherwise.
|
||||
*
|
||||
* @return {number} Get the next token from the stream, or
|
||||
* end_of_stream.
|
||||
*/
|
||||
read: function() {
|
||||
if (!this.tokens.length)
|
||||
return end_of_stream;
|
||||
return this.tokens.shift();
|
||||
},
|
||||
|
||||
/**
|
||||
* When one or more tokens are prepended to a stream, those tokens
|
||||
* must be inserted, in given order, before the first token in the
|
||||
* stream.
|
||||
*
|
||||
* @param {(number|!Array.<number>)} token The token(s) to prepend to the stream.
|
||||
*/
|
||||
prepend: function(token) {
|
||||
if (Array.isArray(token)) {
|
||||
var tokens = /**@type {!Array.<number>}*/(token);
|
||||
while (tokens.length)
|
||||
this.tokens.unshift(tokens.pop());
|
||||
} else {
|
||||
this.tokens.unshift(token);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* When one or more tokens are pushed to a stream, those tokens
|
||||
* must be inserted, in given order, after the last token in the
|
||||
* stream.
|
||||
*
|
||||
* @param {(number|!Array.<number>)} token The tokens(s) to prepend to the stream.
|
||||
*/
|
||||
push: function(token) {
|
||||
if (Array.isArray(token)) {
|
||||
var tokens = /**@type {!Array.<number>}*/(token);
|
||||
while (tokens.length)
|
||||
this.tokens.push(tokens.shift());
|
||||
} else {
|
||||
this.tokens.push(token);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// 4. Encodings
|
||||
//
|
||||
|
||||
// 4.1 Encoders and decoders
|
||||
|
||||
/** @const */
|
||||
var finished = -1;
|
||||
|
||||
/**
|
||||
* @param {boolean} fatal If true, decoding errors raise an exception.
|
||||
* @param {number=} opt_code_point Override the standard fallback code point.
|
||||
* @return {number} The code point to insert on a decoding error.
|
||||
*/
|
||||
function decoderError(fatal, opt_code_point) {
|
||||
if (fatal)
|
||||
throw TypeError('Decoder error');
|
||||
return opt_code_point || 0xFFFD;
|
||||
}
|
||||
|
||||
//
|
||||
// 7. API
|
||||
//
|
||||
|
||||
/** @const */ var DEFAULT_ENCODING = 'utf-8';
|
||||
|
||||
// 7.1 Interface TextDecoder
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string=} encoding The label of the encoding;
|
||||
* defaults to 'utf-8'.
|
||||
* @param {Object=} options
|
||||
*/
|
||||
function TextDecoder$1(encoding, options) {
|
||||
if (!(this instanceof TextDecoder$1)) {
|
||||
return new TextDecoder$1(encoding, options);
|
||||
}
|
||||
encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING;
|
||||
if (encoding !== DEFAULT_ENCODING) {
|
||||
throw new Error('Encoding not supported. Only utf-8 is supported');
|
||||
}
|
||||
options = ToDictionary(options);
|
||||
|
||||
/** @private @type {boolean} */
|
||||
this._streaming = false;
|
||||
/** @private @type {boolean} */
|
||||
this._BOMseen = false;
|
||||
/** @private @type {?Decoder} */
|
||||
this._decoder = null;
|
||||
/** @private @type {boolean} */
|
||||
this._fatal = Boolean(options['fatal']);
|
||||
/** @private @type {boolean} */
|
||||
this._ignoreBOM = Boolean(options['ignoreBOM']);
|
||||
|
||||
Object.defineProperty(this, 'encoding', {value: 'utf-8'});
|
||||
Object.defineProperty(this, 'fatal', {value: this._fatal});
|
||||
Object.defineProperty(this, 'ignoreBOM', {value: this._ignoreBOM});
|
||||
}
|
||||
|
||||
TextDecoder$1.prototype = {
|
||||
/**
|
||||
* @param {ArrayBufferView=} input The buffer of bytes to decode.
|
||||
* @param {Object=} options
|
||||
* @return {string} The decoded string.
|
||||
*/
|
||||
decode: function decode(input, options) {
|
||||
var bytes;
|
||||
if (typeof input === 'object' && input instanceof ArrayBuffer) {
|
||||
bytes = new Uint8Array(input);
|
||||
} else if (typeof input === 'object' && 'buffer' in input &&
|
||||
input.buffer instanceof ArrayBuffer) {
|
||||
bytes = new Uint8Array(input.buffer,
|
||||
input.byteOffset,
|
||||
input.byteLength);
|
||||
} else {
|
||||
bytes = new Uint8Array(0);
|
||||
}
|
||||
|
||||
options = ToDictionary(options);
|
||||
|
||||
if (!this._streaming) {
|
||||
this._decoder = new UTF8Decoder({fatal: this._fatal});
|
||||
this._BOMseen = false;
|
||||
}
|
||||
this._streaming = Boolean(options['stream']);
|
||||
|
||||
var input_stream = new Stream(bytes);
|
||||
|
||||
var code_points = [];
|
||||
|
||||
/** @type {?(number|!Array.<number>)} */
|
||||
var result;
|
||||
|
||||
while (!input_stream.endOfStream()) {
|
||||
result = this._decoder.handler(input_stream, input_stream.read());
|
||||
if (result === finished)
|
||||
break;
|
||||
if (result === null)
|
||||
continue;
|
||||
if (Array.isArray(result))
|
||||
code_points.push.apply(code_points, /**@type {!Array.<number>}*/(result));
|
||||
else
|
||||
code_points.push(result);
|
||||
}
|
||||
if (!this._streaming) {
|
||||
do {
|
||||
result = this._decoder.handler(input_stream, input_stream.read());
|
||||
if (result === finished)
|
||||
break;
|
||||
if (result === null)
|
||||
continue;
|
||||
if (Array.isArray(result))
|
||||
code_points.push.apply(code_points, /**@type {!Array.<number>}*/(result));
|
||||
else
|
||||
code_points.push(result);
|
||||
} while (!input_stream.endOfStream());
|
||||
this._decoder = null;
|
||||
}
|
||||
|
||||
if (code_points.length) {
|
||||
// If encoding is one of utf-8, utf-16be, and utf-16le, and
|
||||
// ignore BOM flag and BOM seen flag are unset, run these
|
||||
// subsubsteps:
|
||||
if (['utf-8'].indexOf(this.encoding) !== -1 &&
|
||||
!this._ignoreBOM && !this._BOMseen) {
|
||||
// If token is U+FEFF, set BOM seen flag.
|
||||
if (code_points[0] === 0xFEFF) {
|
||||
this._BOMseen = true;
|
||||
code_points.shift();
|
||||
} else {
|
||||
// Otherwise, if token is not end-of-stream, set BOM seen
|
||||
// flag and append token to output.
|
||||
this._BOMseen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codePointsToString(code_points);
|
||||
}
|
||||
};
|
||||
|
||||
// 7.2 Interface TextEncoder
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string=} encoding The label of the encoding;
|
||||
* defaults to 'utf-8'.
|
||||
* @param {Object=} options
|
||||
*/
|
||||
function TextEncoder$1(encoding, options) {
|
||||
if (!(this instanceof TextEncoder$1))
|
||||
return new TextEncoder$1(encoding, options);
|
||||
encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING;
|
||||
if (encoding !== DEFAULT_ENCODING) {
|
||||
throw new Error('Encoding not supported. Only utf-8 is supported');
|
||||
}
|
||||
options = ToDictionary(options);
|
||||
|
||||
/** @private @type {boolean} */
|
||||
this._streaming = false;
|
||||
/** @private @type {?Encoder} */
|
||||
this._encoder = null;
|
||||
/** @private @type {{fatal: boolean}} */
|
||||
this._options = {fatal: Boolean(options['fatal'])};
|
||||
|
||||
Object.defineProperty(this, 'encoding', {value: 'utf-8'});
|
||||
}
|
||||
|
||||
TextEncoder$1.prototype = {
|
||||
/**
|
||||
* @param {string=} opt_string The string to encode.
|
||||
* @param {Object=} options
|
||||
* @return {Uint8Array} Encoded bytes, as a Uint8Array.
|
||||
*/
|
||||
encode: function encode(opt_string, options) {
|
||||
opt_string = opt_string ? String(opt_string) : '';
|
||||
options = ToDictionary(options);
|
||||
|
||||
// NOTE: This option is nonstandard. None of the encodings
|
||||
// permitted for encoding (i.e. UTF-8, UTF-16) are stateful,
|
||||
// so streaming is not necessary.
|
||||
if (!this._streaming)
|
||||
this._encoder = new UTF8Encoder(this._options);
|
||||
this._streaming = Boolean(options['stream']);
|
||||
|
||||
var bytes = [];
|
||||
var input_stream = new Stream(stringToCodePoints(opt_string));
|
||||
/** @type {?(number|!Array.<number>)} */
|
||||
var result;
|
||||
while (!input_stream.endOfStream()) {
|
||||
result = this._encoder.handler(input_stream, input_stream.read());
|
||||
if (result === finished)
|
||||
break;
|
||||
if (Array.isArray(result))
|
||||
bytes.push.apply(bytes, /**@type {!Array.<number>}*/(result));
|
||||
else
|
||||
bytes.push(result);
|
||||
}
|
||||
if (!this._streaming) {
|
||||
while (true) {
|
||||
result = this._encoder.handler(input_stream, input_stream.read());
|
||||
if (result === finished)
|
||||
break;
|
||||
if (Array.isArray(result))
|
||||
bytes.push.apply(bytes, /**@type {!Array.<number>}*/(result));
|
||||
else
|
||||
bytes.push(result);
|
||||
}
|
||||
this._encoder = null;
|
||||
}
|
||||
return new Uint8Array(bytes);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// 8. The encoding
|
||||
//
|
||||
|
||||
// 8.1 utf-8
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {Decoder}
|
||||
* @param {{fatal: boolean}} options
|
||||
*/
|
||||
function UTF8Decoder(options) {
|
||||
var fatal = options.fatal;
|
||||
|
||||
// utf-8's decoder's has an associated utf-8 code point, utf-8
|
||||
// bytes seen, and utf-8 bytes needed (all initially 0), a utf-8
|
||||
// lower boundary (initially 0x80), and a utf-8 upper boundary
|
||||
// (initially 0xBF).
|
||||
var /** @type {number} */ utf8_code_point = 0,
|
||||
/** @type {number} */ utf8_bytes_seen = 0,
|
||||
/** @type {number} */ utf8_bytes_needed = 0,
|
||||
/** @type {number} */ utf8_lower_boundary = 0x80,
|
||||
/** @type {number} */ utf8_upper_boundary = 0xBF;
|
||||
|
||||
/**
|
||||
* @param {Stream} stream The stream of bytes being decoded.
|
||||
* @param {number} bite The next byte read from the stream.
|
||||
* @return {?(number|!Array.<number>)} The next code point(s)
|
||||
* decoded, or null if not enough data exists in the input
|
||||
* stream to decode a complete code point.
|
||||
*/
|
||||
this.handler = function(stream, bite) {
|
||||
// 1. If byte is end-of-stream and utf-8 bytes needed is not 0,
|
||||
// set utf-8 bytes needed to 0 and return error.
|
||||
if (bite === end_of_stream && utf8_bytes_needed !== 0) {
|
||||
utf8_bytes_needed = 0;
|
||||
return decoderError(fatal);
|
||||
}
|
||||
|
||||
// 2. If byte is end-of-stream, return finished.
|
||||
if (bite === end_of_stream)
|
||||
return finished;
|
||||
|
||||
// 3. If utf-8 bytes needed is 0, based on byte:
|
||||
if (utf8_bytes_needed === 0) {
|
||||
|
||||
// 0x00 to 0x7F
|
||||
if (inRange(bite, 0x00, 0x7F)) {
|
||||
// Return a code point whose value is byte.
|
||||
return bite;
|
||||
}
|
||||
|
||||
// 0xC2 to 0xDF
|
||||
if (inRange(bite, 0xC2, 0xDF)) {
|
||||
// Set utf-8 bytes needed to 1 and utf-8 code point to byte
|
||||
// − 0xC0.
|
||||
utf8_bytes_needed = 1;
|
||||
utf8_code_point = bite - 0xC0;
|
||||
}
|
||||
|
||||
// 0xE0 to 0xEF
|
||||
else if (inRange(bite, 0xE0, 0xEF)) {
|
||||
// 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0.
|
||||
if (bite === 0xE0)
|
||||
utf8_lower_boundary = 0xA0;
|
||||
// 2. If byte is 0xED, set utf-8 upper boundary to 0x9F.
|
||||
if (bite === 0xED)
|
||||
utf8_upper_boundary = 0x9F;
|
||||
// 3. Set utf-8 bytes needed to 2 and utf-8 code point to
|
||||
// byte − 0xE0.
|
||||
utf8_bytes_needed = 2;
|
||||
utf8_code_point = bite - 0xE0;
|
||||
}
|
||||
|
||||
// 0xF0 to 0xF4
|
||||
else if (inRange(bite, 0xF0, 0xF4)) {
|
||||
// 1. If byte is 0xF0, set utf-8 lower boundary to 0x90.
|
||||
if (bite === 0xF0)
|
||||
utf8_lower_boundary = 0x90;
|
||||
// 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F.
|
||||
if (bite === 0xF4)
|
||||
utf8_upper_boundary = 0x8F;
|
||||
// 3. Set utf-8 bytes needed to 3 and utf-8 code point to
|
||||
// byte − 0xF0.
|
||||
utf8_bytes_needed = 3;
|
||||
utf8_code_point = bite - 0xF0;
|
||||
}
|
||||
|
||||
// Otherwise
|
||||
else {
|
||||
// Return error.
|
||||
return decoderError(fatal);
|
||||
}
|
||||
|
||||
// Then (byte is in the range 0xC2 to 0xF4) set utf-8 code
|
||||
// point to utf-8 code point << (6 × utf-8 bytes needed) and
|
||||
// return continue.
|
||||
utf8_code_point = utf8_code_point << (6 * utf8_bytes_needed);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 4. If byte is not in the range utf-8 lower boundary to utf-8
|
||||
// upper boundary, run these substeps:
|
||||
if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) {
|
||||
|
||||
// 1. Set utf-8 code point, utf-8 bytes needed, and utf-8
|
||||
// bytes seen to 0, set utf-8 lower boundary to 0x80, and set
|
||||
// utf-8 upper boundary to 0xBF.
|
||||
utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0;
|
||||
utf8_lower_boundary = 0x80;
|
||||
utf8_upper_boundary = 0xBF;
|
||||
|
||||
// 2. Prepend byte to stream.
|
||||
stream.prepend(bite);
|
||||
|
||||
// 3. Return error.
|
||||
return decoderError(fatal);
|
||||
}
|
||||
|
||||
// 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary
|
||||
// to 0xBF.
|
||||
utf8_lower_boundary = 0x80;
|
||||
utf8_upper_boundary = 0xBF;
|
||||
|
||||
// 6. Increase utf-8 bytes seen by one and set utf-8 code point
|
||||
// to utf-8 code point + (byte − 0x80) << (6 × (utf-8 bytes
|
||||
// needed − utf-8 bytes seen)).
|
||||
utf8_bytes_seen += 1;
|
||||
utf8_code_point += (bite - 0x80) << (6 * (utf8_bytes_needed - utf8_bytes_seen));
|
||||
|
||||
// 7. If utf-8 bytes seen is not equal to utf-8 bytes needed,
|
||||
// continue.
|
||||
if (utf8_bytes_seen !== utf8_bytes_needed)
|
||||
return null;
|
||||
|
||||
// 8. Let code point be utf-8 code point.
|
||||
var code_point = utf8_code_point;
|
||||
|
||||
// 9. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes
|
||||
// seen to 0.
|
||||
utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0;
|
||||
|
||||
// 10. Return a code point whose value is code point.
|
||||
return code_point;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {Encoder}
|
||||
* @param {{fatal: boolean}} options
|
||||
*/
|
||||
function UTF8Encoder(options) {
|
||||
var fatal = options.fatal;
|
||||
/**
|
||||
* @param {Stream} stream Input stream.
|
||||
* @param {number} code_point Next code point read from the stream.
|
||||
* @return {(number|!Array.<number>)} Byte(s) to emit.
|
||||
*/
|
||||
this.handler = function(stream, code_point) {
|
||||
// 1. If code point is end-of-stream, return finished.
|
||||
if (code_point === end_of_stream)
|
||||
return finished;
|
||||
|
||||
// 2. If code point is in the range U+0000 to U+007F, return a
|
||||
// byte whose value is code point.
|
||||
if (inRange(code_point, 0x0000, 0x007f))
|
||||
return code_point;
|
||||
|
||||
// 3. Set count and offset based on the range code point is in:
|
||||
var count, offset;
|
||||
// U+0080 to U+07FF: 1 and 0xC0
|
||||
if (inRange(code_point, 0x0080, 0x07FF)) {
|
||||
count = 1;
|
||||
offset = 0xC0;
|
||||
}
|
||||
// U+0800 to U+FFFF: 2 and 0xE0
|
||||
else if (inRange(code_point, 0x0800, 0xFFFF)) {
|
||||
count = 2;
|
||||
offset = 0xE0;
|
||||
}
|
||||
// U+10000 to U+10FFFF: 3 and 0xF0
|
||||
else if (inRange(code_point, 0x10000, 0x10FFFF)) {
|
||||
count = 3;
|
||||
offset = 0xF0;
|
||||
}
|
||||
|
||||
// 4.Let bytes be a byte sequence whose first byte is (code
|
||||
// point >> (6 × count)) + offset.
|
||||
var bytes = [(code_point >> (6 * count)) + offset];
|
||||
|
||||
// 5. Run these substeps while count is greater than 0:
|
||||
while (count > 0) {
|
||||
|
||||
// 1. Set temp to code point >> (6 × (count − 1)).
|
||||
var temp = code_point >> (6 * (count - 1));
|
||||
|
||||
// 2. Append to bytes 0x80 | (temp & 0x3F).
|
||||
bytes.push(0x80 | (temp & 0x3F));
|
||||
|
||||
// 3. Decrease count by one.
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
// 6. Return bytes bytes, in order.
|
||||
return bytes;
|
||||
};
|
||||
}
|
||||
|
||||
function getGlobal() {
|
||||
if (typeof self !== 'undefined') return self;
|
||||
if (typeof global !== 'undefined') return global;
|
||||
throw new Error('No global found');
|
||||
}
|
||||
|
||||
if (typeof TextDecoder !== 'function') {
|
||||
getGlobal().TextDecoder = TextDecoder$1;
|
||||
}
|
||||
|
||||
if (typeof TextEncoder !== 'function') {
|
||||
getGlobal().TextEncoder = TextEncoder$1;
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,49 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const SonicBoom = require('../')
|
||||
const { file, runTests } = require('./helper')
|
||||
|
||||
runTests(buildTests)
|
||||
|
||||
function buildTests (test, sync) {
|
||||
// Reset the umask for testing
|
||||
process.umask(0o000)
|
||||
|
||||
test('destroy', (t) => {
|
||||
t.plan(5)
|
||||
|
||||
const dest = file()
|
||||
const fd = fs.openSync(dest, 'w')
|
||||
const stream = new SonicBoom({ fd, sync })
|
||||
|
||||
t.ok(stream.write('hello world\n'))
|
||||
stream.destroy()
|
||||
t.throws(() => { stream.write('hello world\n') })
|
||||
|
||||
fs.readFile(dest, 'utf8', function (err, data) {
|
||||
t.error(err)
|
||||
t.equal(data, 'hello world\n')
|
||||
})
|
||||
|
||||
stream.on('finish', () => {
|
||||
t.fail('finish emitted')
|
||||
})
|
||||
|
||||
stream.on('close', () => {
|
||||
t.pass('close emitted')
|
||||
})
|
||||
})
|
||||
|
||||
test('destroy while opening', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
const dest = file()
|
||||
const stream = new SonicBoom({ dest })
|
||||
|
||||
stream.destroy()
|
||||
stream.on('close', () => {
|
||||
t.pass('close emitted')
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* SHA2-256 a.k.a. sha256. In JS, it is the fastest hash, even faster than Blake3.
|
||||
*
|
||||
* To break sha256 using birthday attack, attackers need to try 2^128 hashes.
|
||||
* BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
|
||||
*
|
||||
* Check out [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
|
||||
* @module
|
||||
* @deprecated
|
||||
*/
|
||||
import { SHA224 as SHA224n, sha224 as sha224n, SHA256 as SHA256n, sha256 as sha256n, } from "./sha2.js";
|
||||
/** @deprecated Use import from `noble/hashes/sha2` module */
|
||||
export const SHA256 = SHA256n;
|
||||
/** @deprecated Use import from `noble/hashes/sha2` module */
|
||||
export const sha256 = sha256n;
|
||||
/** @deprecated Use import from `noble/hashes/sha2` module */
|
||||
export const SHA224 = SHA224n;
|
||||
/** @deprecated Use import from `noble/hashes/sha2` module */
|
||||
export const sha224 = sha224n;
|
||||
//# sourceMappingURL=sha256.js.map
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_class_check_private_static_field_descriptor.js";
|
||||
@@ -0,0 +1,223 @@
|
||||
'use strict';
|
||||
|
||||
//
|
||||
// Allowed token characters:
|
||||
//
|
||||
// '!', '#', '$', '%', '&', ''', '*', '+', '-',
|
||||
// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
|
||||
//
|
||||
// tokenChars[32] === 0 // ' '
|
||||
// tokenChars[33] === 1 // '!'
|
||||
// tokenChars[34] === 0 // '"'
|
||||
// ...
|
||||
//
|
||||
// prettier-ignore
|
||||
const tokenChars = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
|
||||
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
|
||||
];
|
||||
|
||||
/**
|
||||
* Adds an offer to the map of extension offers or a parameter to the map of
|
||||
* parameters.
|
||||
*
|
||||
* @param {Object} dest The map of extension offers or parameters
|
||||
* @param {String} name The extension or parameter name
|
||||
* @param {(Object|Boolean|String)} elem The extension parameters or the
|
||||
* parameter value
|
||||
* @private
|
||||
*/
|
||||
function push(dest, name, elem) {
|
||||
if (dest[name] === undefined) dest[name] = [elem];
|
||||
else dest[name].push(elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the `Sec-WebSocket-Extensions` header into an object.
|
||||
*
|
||||
* @param {String} header The field value of the header
|
||||
* @return {Object} The parsed object
|
||||
* @public
|
||||
*/
|
||||
function parse(header) {
|
||||
const offers = Object.create(null);
|
||||
|
||||
if (header === undefined || header === '') return offers;
|
||||
|
||||
let params = Object.create(null);
|
||||
let mustUnescape = false;
|
||||
let isEscaping = false;
|
||||
let inQuotes = false;
|
||||
let extensionName;
|
||||
let paramName;
|
||||
let start = -1;
|
||||
let end = -1;
|
||||
let i = 0;
|
||||
|
||||
for (; i < header.length; i++) {
|
||||
const code = header.charCodeAt(i);
|
||||
|
||||
if (extensionName === undefined) {
|
||||
if (end === -1 && tokenChars[code] === 1) {
|
||||
if (start === -1) start = i;
|
||||
} else if (code === 0x20 /* ' ' */ || code === 0x09 /* '\t' */) {
|
||||
if (end === -1 && start !== -1) end = i;
|
||||
} else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
|
||||
if (start === -1) {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
|
||||
if (end === -1) end = i;
|
||||
const name = header.slice(start, end);
|
||||
if (code === 0x2c) {
|
||||
push(offers, name, params);
|
||||
params = Object.create(null);
|
||||
} else {
|
||||
extensionName = name;
|
||||
}
|
||||
|
||||
start = end = -1;
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
} else if (paramName === undefined) {
|
||||
if (end === -1 && tokenChars[code] === 1) {
|
||||
if (start === -1) start = i;
|
||||
} else if (code === 0x20 || code === 0x09) {
|
||||
if (end === -1 && start !== -1) end = i;
|
||||
} else if (code === 0x3b || code === 0x2c) {
|
||||
if (start === -1) {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
|
||||
if (end === -1) end = i;
|
||||
push(params, header.slice(start, end), true);
|
||||
if (code === 0x2c) {
|
||||
push(offers, extensionName, params);
|
||||
params = Object.create(null);
|
||||
extensionName = undefined;
|
||||
}
|
||||
|
||||
start = end = -1;
|
||||
} else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {
|
||||
paramName = header.slice(start, i);
|
||||
start = end = -1;
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// The value of a quoted-string after unescaping must conform to the
|
||||
// token ABNF, so only token characters are valid.
|
||||
// Ref: https://tools.ietf.org/html/rfc6455#section-9.1
|
||||
//
|
||||
if (isEscaping) {
|
||||
if (tokenChars[code] !== 1) {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
if (start === -1) start = i;
|
||||
else if (!mustUnescape) mustUnescape = true;
|
||||
isEscaping = false;
|
||||
} else if (inQuotes) {
|
||||
if (tokenChars[code] === 1) {
|
||||
if (start === -1) start = i;
|
||||
} else if (code === 0x22 /* '"' */ && start !== -1) {
|
||||
inQuotes = false;
|
||||
end = i;
|
||||
} else if (code === 0x5c /* '\' */) {
|
||||
isEscaping = true;
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
} else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
|
||||
inQuotes = true;
|
||||
} else if (end === -1 && tokenChars[code] === 1) {
|
||||
if (start === -1) start = i;
|
||||
} else if (start !== -1 && (code === 0x20 || code === 0x09)) {
|
||||
if (end === -1) end = i;
|
||||
} else if (code === 0x3b || code === 0x2c) {
|
||||
if (start === -1) {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
|
||||
if (end === -1) end = i;
|
||||
let value = header.slice(start, end);
|
||||
if (mustUnescape) {
|
||||
value = value.replace(/\\/g, '');
|
||||
mustUnescape = false;
|
||||
}
|
||||
push(params, paramName, value);
|
||||
if (code === 0x2c) {
|
||||
push(offers, extensionName, params);
|
||||
params = Object.create(null);
|
||||
extensionName = undefined;
|
||||
}
|
||||
|
||||
paramName = undefined;
|
||||
start = end = -1;
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected character at index ${i}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (start === -1 || inQuotes) {
|
||||
throw new SyntaxError('Unexpected end of input');
|
||||
}
|
||||
|
||||
if (end === -1) end = i;
|
||||
const token = header.slice(start, end);
|
||||
if (extensionName === undefined) {
|
||||
push(offers, token, params);
|
||||
} else {
|
||||
if (paramName === undefined) {
|
||||
push(params, token, true);
|
||||
} else if (mustUnescape) {
|
||||
push(params, paramName, token.replace(/\\/g, ''));
|
||||
} else {
|
||||
push(params, paramName, token);
|
||||
}
|
||||
push(offers, extensionName, params);
|
||||
}
|
||||
|
||||
return offers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the `Sec-WebSocket-Extensions` header field value.
|
||||
*
|
||||
* @param {Object} extensions The map of extensions and parameters to format
|
||||
* @return {String} A string representing the given object
|
||||
* @public
|
||||
*/
|
||||
function format(extensions) {
|
||||
return Object.keys(extensions)
|
||||
.map((extension) => {
|
||||
let configurations = extensions[extension];
|
||||
if (!Array.isArray(configurations)) configurations = [configurations];
|
||||
return configurations
|
||||
.map((params) => {
|
||||
return [extension]
|
||||
.concat(
|
||||
Object.keys(params).map((k) => {
|
||||
let values = params[k];
|
||||
if (!Array.isArray(values)) values = [values];
|
||||
return values
|
||||
.map((v) => (v === true ? k : `${k}=${v}`))
|
||||
.join('; ');
|
||||
})
|
||||
)
|
||||
.join('; ');
|
||||
})
|
||||
.join(', ');
|
||||
})
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
module.exports = { format, parse };
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"symbolFlags.enum.d.ts","sourceRoot":"","sources":["../../src/enums/symbolFlags.enum.ts"],"names":[],"mappings":"AAEA,oBAAY,WAAW;IACnB,IAAI,IAAI;IACR,sBAAsB,IAAS;IAC/B,mBAAmB,IAAS;IAC5B,QAAQ,IAAS;IACjB,UAAU,IAAS;IACnB,QAAQ,KAAS;IACjB,KAAK,KAAS;IACd,SAAS,KAAS;IAClB,SAAS,MAAS;IAClB,WAAW,MAAS;IACpB,WAAW,MAAS;IACpB,eAAe,OAAU;IACzB,WAAW,OAAU;IACrB,aAAa,OAAU;IACvB,MAAM,OAAU;IAChB,WAAW,QAAU;IACrB,WAAW,QAAU;IACrB,WAAW,QAAU;IACrB,SAAS,SAAU;IACnB,aAAa,SAAU;IACvB,SAAS,SAAU;IACnB,WAAW,UAAU;IACrB,KAAK,UAAU;IACf,SAAS,UAAU;IACnB,UAAU,UAAU;IACpB,QAAQ,WAAU;IAClB,SAAS,WAAU;IACnB,UAAU,WAAU;IACpB,aAAa,YAAU;IACvB,mBAAmB,YAAU;IAC7B,mBAAmB,YAAU;IAC7B,YAAY,aAAU;IACtB,GAAG,YAAc;IACjB,IAAI,MAA0B;IAC9B,QAAQ,IAA+C;IACvD,KAAK,SAAgI;IACrI,IAAI,SAAkF;IACtF,SAAS,OAAuC;IAChD,MAAM,OAAgC;IACtC,QAAQ,QAA4B;IACpC,8BAA8B,SAAkC;IAChE,2BAA2B,SAAQ;IACnC,iBAAiB,SAAQ;IACzB,gBAAgB,QAAiC;IACjD,kBAAkB,SAAe;IACjC,gBAAgB,SAA4C;IAC5D,aAAa,SAAyD;IACtE,iBAAiB,SAA8B;IAC/C,mBAAmB,SAAgD;IACnE,iBAAiB,SAA8B;IAC/C,mBAAmB,SAA0D;IAC7E,uBAAuB,IAAO;IAC9B,cAAc,SAAkB;IAChC,mBAAmB,QAAoC;IACvD,mBAAmB,QAAoC;IACvD,gBAAgB,SAAoB;IACpC,qBAAqB,SAAwB;IAC7C,iBAAiB,SAAO;IACxB,aAAa,UAAQ;IACrB,YAAY,UAA8E;IAC1F,cAAc,MAAwC;IACtD,WAAW,MAAqC;IAChD,kBAAkB,QAAsB;IACxC,WAAW,SAA+B;IAC1C,6BAA6B,MAA+B;IAC5D,mCAAmC,OAAiC;IACpE,YAAY,UAAwE;IACpF,oBAAoB,OAA6D;CACpF"}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,43 @@
|
||||
import { expectType, expectError } from 'tsd'
|
||||
import sjson from '..'
|
||||
|
||||
expectError(sjson.parse(null))
|
||||
expectType<any>(sjson.parse('{"anything":0}'))
|
||||
|
||||
sjson.parse('"test"', null, { protoAction: 'remove' })
|
||||
expectError(sjson.parse('"test"', null, { protoAction: 'incorrect' }))
|
||||
sjson.parse('"test"', null, { constructorAction: 'ignore' })
|
||||
expectError(sjson.parse('"test"', null, { constructorAction: 'incorrect' }))
|
||||
expectError(sjson.parse('"test"', { constructorAction: 'incorrect' }))
|
||||
sjson.parse('test', { constructorAction: 'remove' })
|
||||
sjson.parse('test', { protoAction: 'ignore' })
|
||||
sjson.parse('test', () => {}, { protoAction: 'ignore', constructorAction: 'remove' })
|
||||
sjson.parse('"test"', null, { safe: true })
|
||||
sjson.parse('"test"', { safe: true })
|
||||
sjson.parse('test', () => {}, { safe: false })
|
||||
sjson.parse('test', { protoAction: 'remove', safe: true })
|
||||
expectError(sjson.parse('"test"', null, { safe: 'incorrect' }))
|
||||
|
||||
sjson.safeParse('"test"', null)
|
||||
sjson.safeParse('"test"')
|
||||
expectError(sjson.safeParse(null))
|
||||
|
||||
sjson.scan({}, { protoAction: 'remove' })
|
||||
sjson.scan({}, { protoAction: 'ignore' })
|
||||
sjson.scan({}, { constructorAction: 'error' })
|
||||
sjson.scan({}, { constructorAction: 'ignore' })
|
||||
sjson.scan([], {})
|
||||
sjson.scan({}, { safe: true })
|
||||
sjson.scan({}, { protoAction: 'remove', safe: false })
|
||||
expectError(sjson.scan({}, { safe: 'incorrect' }))
|
||||
|
||||
declare const input: Buffer
|
||||
sjson.parse(input)
|
||||
sjson.safeParse(input)
|
||||
|
||||
sjson.parse('{"anything":0}', (key, value) => {
|
||||
expectType<string>(key)
|
||||
})
|
||||
sjson.safeParse('{"anything":0}', (key, value) => {
|
||||
expectType<string>(key)
|
||||
})
|
||||
Reference in New Issue
Block a user