WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import _typeof from "./typeof.js";
|
||||
function _regeneratorValues(e) {
|
||||
if (null != e) {
|
||||
var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"],
|
||||
r = 0;
|
||||
if (t) return t.call(e);
|
||||
if ("function" == typeof e.next) return e;
|
||||
if (!isNaN(e.length)) return {
|
||||
next: function next() {
|
||||
return e && r >= e.length && (e = void 0), {
|
||||
value: e && e[r++],
|
||||
done: !e
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
throw new TypeError(_typeof(e) + " is not iterable");
|
||||
}
|
||||
export { _regeneratorValues as default };
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "p-limit",
|
||||
"version": "3.1.0",
|
||||
"description": "Run multiple promise-returning & async functions with limited concurrency",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/p-limit",
|
||||
"funding": "https://github.com/sponsors/sindresorhus",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "https://sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava && tsd"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts"
|
||||
],
|
||||
"keywords": [
|
||||
"promise",
|
||||
"limit",
|
||||
"limited",
|
||||
"concurrency",
|
||||
"throttle",
|
||||
"throat",
|
||||
"rate",
|
||||
"batch",
|
||||
"ratelimit",
|
||||
"task",
|
||||
"queue",
|
||||
"async",
|
||||
"await",
|
||||
"promises",
|
||||
"bluebird"
|
||||
],
|
||||
"dependencies": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^2.4.0",
|
||||
"delay": "^4.4.0",
|
||||
"in-range": "^2.0.0",
|
||||
"random-int": "^2.0.1",
|
||||
"time-span": "^4.0.0",
|
||||
"tsd": "^0.13.1",
|
||||
"xo": "^0.35.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const node_path_1 = require("node:path");
|
||||
const ts = __importStar(require("typescript"));
|
||||
const util_1 = require("../util");
|
||||
exports.default = (0, util_1.createRule)({
|
||||
name: 'no-unnecessary-type-constraint',
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Disallow unnecessary constraints on generic types',
|
||||
recommended: 'recommended',
|
||||
},
|
||||
hasSuggestions: true,
|
||||
messages: {
|
||||
removeUnnecessaryConstraint: 'Remove the unnecessary `{{constraint}}` constraint.',
|
||||
unnecessaryConstraint: 'Constraining the generic type `{{name}}` to `{{constraint}}` does nothing and is unnecessary.',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
create(context) {
|
||||
// In theory, we could use the type checker for more advanced constraint types...
|
||||
// ...but in practice, these types are rare, and likely not worth requiring type info.
|
||||
// https://github.com/typescript-eslint/typescript-eslint/pull/2516#discussion_r495731858
|
||||
const unnecessaryConstraints = new Map([
|
||||
[utils_1.AST_NODE_TYPES.TSAnyKeyword, 'any'],
|
||||
[utils_1.AST_NODE_TYPES.TSUnknownKeyword, 'unknown'],
|
||||
]);
|
||||
function checkRequiresGenericDeclarationDisambiguation(filename) {
|
||||
const pathExt = (0, node_path_1.extname)(filename).toLocaleLowerCase();
|
||||
switch (pathExt) {
|
||||
case ts.Extension.Cts:
|
||||
case ts.Extension.Mts:
|
||||
case ts.Extension.Tsx:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const requiresGenericDeclarationDisambiguation = checkRequiresGenericDeclarationDisambiguation(context.filename);
|
||||
const checkNode = (node, inArrowFunction) => {
|
||||
const constraint = unnecessaryConstraints.get(node.constraint.type);
|
||||
function shouldAddTrailingComma() {
|
||||
if (!inArrowFunction || !requiresGenericDeclarationDisambiguation) {
|
||||
return false;
|
||||
}
|
||||
// Only <T>() => {} would need trailing comma
|
||||
return (node.parent.params.length ===
|
||||
1 &&
|
||||
context.sourceCode.getTokensAfter(node)[0].value !== ',' &&
|
||||
!node.default);
|
||||
}
|
||||
if (constraint) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'unnecessaryConstraint',
|
||||
data: {
|
||||
name: node.name.name,
|
||||
constraint,
|
||||
},
|
||||
suggest: [
|
||||
{
|
||||
messageId: 'removeUnnecessaryConstraint',
|
||||
data: {
|
||||
constraint,
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.replaceTextRange([node.name.range[1], node.constraint.range[1]], shouldAddTrailingComma() ? ',' : '');
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
};
|
||||
return {
|
||||
':not(ArrowFunctionExpression) > TSTypeParameterDeclaration > TSTypeParameter[constraint]'(node) {
|
||||
checkNode(node, false);
|
||||
},
|
||||
'ArrowFunctionExpression > TSTypeParameterDeclaration > TSTypeParameter[constraint]'(node) {
|
||||
checkNode(node, true);
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,457 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createStandardJSONSchemaMethod = exports.createToJSONSchemaMethod = void 0;
|
||||
exports.initializeContext = initializeContext;
|
||||
exports.process = process;
|
||||
exports.extractDefs = extractDefs;
|
||||
exports.finalize = finalize;
|
||||
const registries_js_1 = require("./registries.cjs");
|
||||
// function initializeContext<T extends schemas.$ZodType>(inputs: JSONSchemaGeneratorParams<T>): ToJSONSchemaContext<T> {
|
||||
// return {
|
||||
// processor: inputs.processor,
|
||||
// metadataRegistry: inputs.metadata ?? globalRegistry,
|
||||
// target: inputs.target ?? "draft-2020-12",
|
||||
// unrepresentable: inputs.unrepresentable ?? "throw",
|
||||
// };
|
||||
// }
|
||||
function initializeContext(params) {
|
||||
// Normalize target: convert old non-hyphenated versions to hyphenated versions
|
||||
let target = params?.target ?? "draft-2020-12";
|
||||
if (target === "draft-4")
|
||||
target = "draft-04";
|
||||
if (target === "draft-7")
|
||||
target = "draft-07";
|
||||
return {
|
||||
processors: params.processors ?? {},
|
||||
metadataRegistry: params?.metadata ?? registries_js_1.globalRegistry,
|
||||
target,
|
||||
unrepresentable: params?.unrepresentable ?? "throw",
|
||||
override: params?.override ?? (() => { }),
|
||||
io: params?.io ?? "output",
|
||||
counter: 0,
|
||||
seen: new Map(),
|
||||
cycles: params?.cycles ?? "ref",
|
||||
reused: params?.reused ?? "inline",
|
||||
external: params?.external ?? undefined,
|
||||
};
|
||||
}
|
||||
function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
||||
var _a;
|
||||
const def = schema._zod.def;
|
||||
// check for schema in seens
|
||||
const seen = ctx.seen.get(schema);
|
||||
if (seen) {
|
||||
seen.count++;
|
||||
// check if cycle
|
||||
const isCycle = _params.schemaPath.includes(schema);
|
||||
if (isCycle) {
|
||||
seen.cycle = _params.path;
|
||||
}
|
||||
return seen.schema;
|
||||
}
|
||||
// initialize
|
||||
const result = { schema: {}, count: 1, cycle: undefined, path: _params.path };
|
||||
ctx.seen.set(schema, result);
|
||||
// custom method overrides default behavior
|
||||
const overrideSchema = schema._zod.toJSONSchema?.();
|
||||
if (overrideSchema) {
|
||||
result.schema = overrideSchema;
|
||||
}
|
||||
else {
|
||||
const params = {
|
||||
..._params,
|
||||
schemaPath: [..._params.schemaPath, schema],
|
||||
path: _params.path,
|
||||
};
|
||||
if (schema._zod.processJSONSchema) {
|
||||
schema._zod.processJSONSchema(ctx, result.schema, params);
|
||||
}
|
||||
else {
|
||||
const _json = result.schema;
|
||||
const processor = ctx.processors[def.type];
|
||||
if (!processor) {
|
||||
throw new Error(`[toJSONSchema]: Non-representable type encountered: ${def.type}`);
|
||||
}
|
||||
processor(schema, ctx, _json, params);
|
||||
}
|
||||
const parent = schema._zod.parent;
|
||||
if (parent) {
|
||||
// Also set ref if processor didn't (for inheritance)
|
||||
if (!result.ref)
|
||||
result.ref = parent;
|
||||
process(parent, ctx, params);
|
||||
ctx.seen.get(parent).isParent = true;
|
||||
}
|
||||
}
|
||||
// metadata
|
||||
const meta = ctx.metadataRegistry.get(schema);
|
||||
if (meta)
|
||||
Object.assign(result.schema, meta);
|
||||
if (ctx.io === "input" && isTransforming(schema)) {
|
||||
// examples/defaults only apply to output type of pipe
|
||||
delete result.schema.examples;
|
||||
delete result.schema.default;
|
||||
}
|
||||
// set prefault as default
|
||||
if (ctx.io === "input" && "_prefault" in result.schema)
|
||||
(_a = result.schema).default ?? (_a.default = result.schema._prefault);
|
||||
delete result.schema._prefault;
|
||||
// pulling fresh from ctx.seen in case it was overwritten
|
||||
const _result = ctx.seen.get(schema);
|
||||
return _result.schema;
|
||||
}
|
||||
function extractDefs(ctx, schema
|
||||
// params: EmitParams
|
||||
) {
|
||||
// iterate over seen map;
|
||||
const root = ctx.seen.get(schema);
|
||||
if (!root)
|
||||
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
||||
// Track ids to detect duplicates across different schemas
|
||||
const idToSchema = new Map();
|
||||
for (const entry of ctx.seen.entries()) {
|
||||
const id = ctx.metadataRegistry.get(entry[0])?.id;
|
||||
if (id) {
|
||||
const existing = idToSchema.get(id);
|
||||
if (existing && existing !== entry[0]) {
|
||||
throw new Error(`Duplicate schema id "${id}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
|
||||
}
|
||||
idToSchema.set(id, entry[0]);
|
||||
}
|
||||
}
|
||||
// returns a ref to the schema
|
||||
// defId will be empty if the ref points to an external schema (or #)
|
||||
const makeURI = (entry) => {
|
||||
// comparing the seen objects because sometimes
|
||||
// multiple schemas map to the same seen object.
|
||||
// e.g. lazy
|
||||
// external is configured
|
||||
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
||||
if (ctx.external) {
|
||||
const externalId = ctx.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${ctx.counter++}`;
|
||||
// check if schema is in the external registry
|
||||
const uriGenerator = ctx.external.uri ?? ((id) => id);
|
||||
if (externalId) {
|
||||
return { ref: uriGenerator(externalId) };
|
||||
}
|
||||
// otherwise, add to __shared
|
||||
const id = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
|
||||
entry[1].defId = id; // set defId so it will be reused if needed
|
||||
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
|
||||
}
|
||||
if (entry[1] === root) {
|
||||
return { ref: "#" };
|
||||
}
|
||||
// self-contained schema
|
||||
const uriPrefix = `#`;
|
||||
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
||||
const defId = entry[1].schema.id ?? `__schema${ctx.counter++}`;
|
||||
return { defId, ref: defUriPrefix + defId };
|
||||
};
|
||||
// stored cached version in `def` property
|
||||
// remove all properties, set $ref
|
||||
const extractToDef = (entry) => {
|
||||
// if the schema is already a reference, do not extract it
|
||||
if (entry[1].schema.$ref) {
|
||||
return;
|
||||
}
|
||||
const seen = entry[1];
|
||||
const { ref, defId } = makeURI(entry);
|
||||
seen.def = { ...seen.schema };
|
||||
// defId won't be set if the schema is a reference to an external schema
|
||||
// or if the schema is the root schema
|
||||
if (defId)
|
||||
seen.defId = defId;
|
||||
// wipe away all properties except $ref
|
||||
const schema = seen.schema;
|
||||
for (const key in schema) {
|
||||
delete schema[key];
|
||||
}
|
||||
schema.$ref = ref;
|
||||
};
|
||||
// throw on cycles
|
||||
// break cycles
|
||||
if (ctx.cycles === "throw") {
|
||||
for (const entry of ctx.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
if (seen.cycle) {
|
||||
throw new Error("Cycle detected: " +
|
||||
`#/${seen.cycle?.join("/")}/<root>` +
|
||||
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
||||
}
|
||||
}
|
||||
}
|
||||
// extract schemas into $defs
|
||||
for (const entry of ctx.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
// convert root schema to # $ref
|
||||
if (schema === entry[0]) {
|
||||
extractToDef(entry); // this has special handling for the root schema
|
||||
continue;
|
||||
}
|
||||
// extract schemas that are in the external registry
|
||||
if (ctx.external) {
|
||||
const ext = ctx.external.registry.get(entry[0])?.id;
|
||||
if (schema !== entry[0] && ext) {
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// extract schemas with `id` meta
|
||||
const id = ctx.metadataRegistry.get(entry[0])?.id;
|
||||
if (id) {
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
// break cycles
|
||||
if (seen.cycle) {
|
||||
// any
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
// extract reused schemas
|
||||
if (seen.count > 1) {
|
||||
if (ctx.reused === "ref") {
|
||||
extractToDef(entry);
|
||||
// biome-ignore lint:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function finalize(ctx, schema) {
|
||||
const root = ctx.seen.get(schema);
|
||||
if (!root)
|
||||
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
||||
// flatten refs - inherit properties from parent schemas
|
||||
const flattenRef = (zodSchema) => {
|
||||
const seen = ctx.seen.get(zodSchema);
|
||||
// already processed
|
||||
if (seen.ref === null)
|
||||
return;
|
||||
const schema = seen.def ?? seen.schema;
|
||||
const _cached = { ...schema };
|
||||
const ref = seen.ref;
|
||||
seen.ref = null; // prevent infinite recursion
|
||||
if (ref) {
|
||||
flattenRef(ref);
|
||||
const refSeen = ctx.seen.get(ref);
|
||||
const refSchema = refSeen.schema;
|
||||
// merge referenced schema into current
|
||||
if (refSchema.$ref && (ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0")) {
|
||||
// older drafts can't combine $ref with other properties
|
||||
schema.allOf = schema.allOf ?? [];
|
||||
schema.allOf.push(refSchema);
|
||||
}
|
||||
else {
|
||||
Object.assign(schema, refSchema);
|
||||
}
|
||||
// restore child's own properties (child wins)
|
||||
Object.assign(schema, _cached);
|
||||
const isParentRef = zodSchema._zod.parent === ref;
|
||||
// For parent chain, child is a refinement - remove parent-only properties
|
||||
if (isParentRef) {
|
||||
for (const key in schema) {
|
||||
if (key === "$ref" || key === "allOf")
|
||||
continue;
|
||||
if (!(key in _cached)) {
|
||||
delete schema[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
// When ref was extracted to $defs, remove properties that match the definition
|
||||
if (refSchema.$ref && refSeen.def) {
|
||||
for (const key in schema) {
|
||||
if (key === "$ref" || key === "allOf")
|
||||
continue;
|
||||
if (key in refSeen.def && JSON.stringify(schema[key]) === JSON.stringify(refSeen.def[key])) {
|
||||
delete schema[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If parent was extracted (has $ref), propagate $ref to this schema
|
||||
// This handles cases like: readonly().meta({id}).describe()
|
||||
// where processor sets ref to innerType but parent should be referenced
|
||||
const parent = zodSchema._zod.parent;
|
||||
if (parent && parent !== ref) {
|
||||
// Ensure parent is processed first so its def has inherited properties
|
||||
flattenRef(parent);
|
||||
const parentSeen = ctx.seen.get(parent);
|
||||
if (parentSeen?.schema.$ref) {
|
||||
schema.$ref = parentSeen.schema.$ref;
|
||||
// De-duplicate with parent's definition
|
||||
if (parentSeen.def) {
|
||||
for (const key in schema) {
|
||||
if (key === "$ref" || key === "allOf")
|
||||
continue;
|
||||
if (key in parentSeen.def && JSON.stringify(schema[key]) === JSON.stringify(parentSeen.def[key])) {
|
||||
delete schema[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// execute overrides
|
||||
ctx.override({
|
||||
zodSchema: zodSchema,
|
||||
jsonSchema: schema,
|
||||
path: seen.path ?? [],
|
||||
});
|
||||
};
|
||||
for (const entry of [...ctx.seen.entries()].reverse()) {
|
||||
flattenRef(entry[0]);
|
||||
}
|
||||
const result = {};
|
||||
if (ctx.target === "draft-2020-12") {
|
||||
result.$schema = "https://json-schema.org/draft/2020-12/schema";
|
||||
}
|
||||
else if (ctx.target === "draft-07") {
|
||||
result.$schema = "http://json-schema.org/draft-07/schema#";
|
||||
}
|
||||
else if (ctx.target === "draft-04") {
|
||||
result.$schema = "http://json-schema.org/draft-04/schema#";
|
||||
}
|
||||
else if (ctx.target === "openapi-3.0") {
|
||||
// OpenAPI 3.0 schema objects should not include a $schema property
|
||||
}
|
||||
else {
|
||||
// Arbitrary string values are allowed but won't have a $schema property set
|
||||
}
|
||||
if (ctx.external?.uri) {
|
||||
const id = ctx.external.registry.get(schema)?.id;
|
||||
if (!id)
|
||||
throw new Error("Schema is missing an `id` property");
|
||||
result.$id = ctx.external.uri(id);
|
||||
}
|
||||
Object.assign(result, root.def ?? root.schema);
|
||||
// The `id` in `.meta()` is a Zod-specific registration tag used to extract
|
||||
// schemas into $defs — it is not user-facing JSON Schema metadata. Strip it
|
||||
// from the output body where it would otherwise leak. The id is preserved
|
||||
// implicitly via the $defs key (and via $ref paths).
|
||||
const rootMetaId = ctx.metadataRegistry.get(schema)?.id;
|
||||
if (rootMetaId !== undefined && result.id === rootMetaId)
|
||||
delete result.id;
|
||||
// build defs object
|
||||
const defs = ctx.external?.defs ?? {};
|
||||
for (const entry of ctx.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
if (seen.def && seen.defId) {
|
||||
if (seen.def.id === seen.defId)
|
||||
delete seen.def.id;
|
||||
defs[seen.defId] = seen.def;
|
||||
}
|
||||
}
|
||||
// set definitions in result
|
||||
if (ctx.external) {
|
||||
}
|
||||
else {
|
||||
if (Object.keys(defs).length > 0) {
|
||||
if (ctx.target === "draft-2020-12") {
|
||||
result.$defs = defs;
|
||||
}
|
||||
else {
|
||||
result.definitions = defs;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
// this "finalizes" this schema and ensures all cycles are removed
|
||||
// each call to finalize() is functionally independent
|
||||
// though the seen map is shared
|
||||
const finalized = JSON.parse(JSON.stringify(result));
|
||||
Object.defineProperty(finalized, "~standard", {
|
||||
value: {
|
||||
...schema["~standard"],
|
||||
jsonSchema: {
|
||||
input: (0, exports.createStandardJSONSchemaMethod)(schema, "input", ctx.processors),
|
||||
output: (0, exports.createStandardJSONSchemaMethod)(schema, "output", ctx.processors),
|
||||
},
|
||||
},
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
});
|
||||
return finalized;
|
||||
}
|
||||
catch (_err) {
|
||||
throw new Error("Error converting schema to JSON.");
|
||||
}
|
||||
}
|
||||
function isTransforming(_schema, _ctx) {
|
||||
const ctx = _ctx ?? { seen: new Set() };
|
||||
if (ctx.seen.has(_schema))
|
||||
return false;
|
||||
ctx.seen.add(_schema);
|
||||
const def = _schema._zod.def;
|
||||
if (def.type === "transform")
|
||||
return true;
|
||||
if (def.type === "array")
|
||||
return isTransforming(def.element, ctx);
|
||||
if (def.type === "set")
|
||||
return isTransforming(def.valueType, ctx);
|
||||
if (def.type === "lazy")
|
||||
return isTransforming(def.getter(), ctx);
|
||||
if (def.type === "promise" ||
|
||||
def.type === "optional" ||
|
||||
def.type === "nonoptional" ||
|
||||
def.type === "nullable" ||
|
||||
def.type === "readonly" ||
|
||||
def.type === "default" ||
|
||||
def.type === "prefault") {
|
||||
return isTransforming(def.innerType, ctx);
|
||||
}
|
||||
if (def.type === "intersection") {
|
||||
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
||||
}
|
||||
if (def.type === "record" || def.type === "map") {
|
||||
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
||||
}
|
||||
if (def.type === "pipe") {
|
||||
if (_schema._zod.traits.has("$ZodCodec"))
|
||||
return true;
|
||||
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
||||
}
|
||||
if (def.type === "object") {
|
||||
for (const key in def.shape) {
|
||||
if (isTransforming(def.shape[key], ctx))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (def.type === "union") {
|
||||
for (const option of def.options) {
|
||||
if (isTransforming(option, ctx))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (def.type === "tuple") {
|
||||
for (const item of def.items) {
|
||||
if (isTransforming(item, ctx))
|
||||
return true;
|
||||
}
|
||||
if (def.rest && isTransforming(def.rest, ctx))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Creates a toJSONSchema method for a schema instance.
|
||||
* This encapsulates the logic of initializing context, processing, extracting defs, and finalizing.
|
||||
*/
|
||||
const createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
|
||||
const ctx = initializeContext({ ...params, processors });
|
||||
process(schema, ctx);
|
||||
extractDefs(ctx, schema);
|
||||
return finalize(ctx, schema);
|
||||
};
|
||||
exports.createToJSONSchemaMethod = createToJSONSchemaMethod;
|
||||
const createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
|
||||
const { libraryOptions, target } = params ?? {};
|
||||
const ctx = initializeContext({ ...(libraryOptions ?? {}), target, io, processors });
|
||||
process(schema, ctx);
|
||||
extractDefs(ctx, schema);
|
||||
return finalize(ctx, schema);
|
||||
};
|
||||
exports.createStandardJSONSchemaMethod = createStandardJSONSchemaMethod;
|
||||
@@ -0,0 +1,146 @@
|
||||
// translate the various posix character classes into unicode properties
|
||||
// this works across all unicode locales
|
||||
// { <posix class>: [<translation>, /u flag required, negated]
|
||||
const posixClasses = {
|
||||
'[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
|
||||
'[:alpha:]': ['\\p{L}\\p{Nl}', true],
|
||||
'[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
|
||||
'[:blank:]': ['\\p{Zs}\\t', true],
|
||||
'[:cntrl:]': ['\\p{Cc}', true],
|
||||
'[:digit:]': ['\\p{Nd}', true],
|
||||
'[:graph:]': ['\\p{Z}\\p{C}', true, true],
|
||||
'[:lower:]': ['\\p{Ll}', true],
|
||||
'[:print:]': ['\\p{C}', true],
|
||||
'[:punct:]': ['\\p{P}', true],
|
||||
'[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
|
||||
'[:upper:]': ['\\p{Lu}', true],
|
||||
'[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
|
||||
'[:xdigit:]': ['A-Fa-f0-9', false],
|
||||
};
|
||||
// only need to escape a few things inside of brace expressions
|
||||
// escapes: [ \ ] -
|
||||
const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
|
||||
// escape all regexp magic characters
|
||||
const regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
// everything has already been escaped, we just have to join
|
||||
const rangesToString = (ranges) => ranges.join('');
|
||||
// takes a glob string at a posix brace expression, and returns
|
||||
// an equivalent regular expression source, and boolean indicating
|
||||
// whether the /u flag needs to be applied, and the number of chars
|
||||
// consumed to parse the character class.
|
||||
// This also removes out of order ranges, and returns ($.) if the
|
||||
// entire class just no good.
|
||||
export const parseClass = (glob, position) => {
|
||||
const pos = position;
|
||||
/* c8 ignore start */
|
||||
if (glob.charAt(pos) !== '[') {
|
||||
throw new Error('not in a brace expression');
|
||||
}
|
||||
/* c8 ignore stop */
|
||||
const ranges = [];
|
||||
const negs = [];
|
||||
let i = pos + 1;
|
||||
let sawStart = false;
|
||||
let uflag = false;
|
||||
let escaping = false;
|
||||
let negate = false;
|
||||
let endPos = pos;
|
||||
let rangeStart = '';
|
||||
WHILE: while (i < glob.length) {
|
||||
const c = glob.charAt(i);
|
||||
if ((c === '!' || c === '^') && i === pos + 1) {
|
||||
negate = true;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (c === ']' && sawStart && !escaping) {
|
||||
endPos = i + 1;
|
||||
break;
|
||||
}
|
||||
sawStart = true;
|
||||
if (c === '\\') {
|
||||
if (!escaping) {
|
||||
escaping = true;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// escaped \ char, fall through and treat like normal char
|
||||
}
|
||||
if (c === '[' && !escaping) {
|
||||
// either a posix class, a collation equivalent, or just a [
|
||||
for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
|
||||
if (glob.startsWith(cls, i)) {
|
||||
// invalid, [a-[] is fine, but not [a-[:alpha]]
|
||||
if (rangeStart) {
|
||||
return ['$.', false, glob.length - pos, true];
|
||||
}
|
||||
i += cls.length;
|
||||
if (neg)
|
||||
negs.push(unip);
|
||||
else
|
||||
ranges.push(unip);
|
||||
uflag = uflag || u;
|
||||
continue WHILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// now it's just a normal character, effectively
|
||||
escaping = false;
|
||||
if (rangeStart) {
|
||||
// throw this range away if it's not valid, but others
|
||||
// can still match.
|
||||
if (c > rangeStart) {
|
||||
ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c));
|
||||
}
|
||||
else if (c === rangeStart) {
|
||||
ranges.push(braceEscape(c));
|
||||
}
|
||||
rangeStart = '';
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// now might be the start of a range.
|
||||
// can be either c-d or c-] or c<more...>] or c] at this point
|
||||
if (glob.startsWith('-]', i + 1)) {
|
||||
ranges.push(braceEscape(c + '-'));
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (glob.startsWith('-', i + 1)) {
|
||||
rangeStart = c;
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
// not the start of a range, just a single character
|
||||
ranges.push(braceEscape(c));
|
||||
i++;
|
||||
}
|
||||
if (endPos < i) {
|
||||
// didn't see the end of the class, not a valid class,
|
||||
// but might still be valid as a literal match.
|
||||
return ['', false, 0, false];
|
||||
}
|
||||
// if we got no ranges and no negates, then we have a range that
|
||||
// cannot possibly match anything, and that poisons the whole glob
|
||||
if (!ranges.length && !negs.length) {
|
||||
return ['$.', false, glob.length - pos, true];
|
||||
}
|
||||
// if we got one positive range, and it's a single character, then that's
|
||||
// not actually a magic pattern, it's just that one literal character.
|
||||
// we should not treat that as "magic", we should just return the literal
|
||||
// character. [_] is a perfectly valid way to escape glob magic chars.
|
||||
if (negs.length === 0 &&
|
||||
ranges.length === 1 &&
|
||||
/^\\?.$/.test(ranges[0]) &&
|
||||
!negate) {
|
||||
const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
|
||||
return [regexpEscape(r), false, endPos - pos, false];
|
||||
}
|
||||
const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']';
|
||||
const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']';
|
||||
const comb = ranges.length && negs.length ? '(' + sranges + '|' + snegs + ')'
|
||||
: ranges.length ? sranges
|
||||
: snegs;
|
||||
return [comb, uflag, endPos - pos, true];
|
||||
};
|
||||
//# sourceMappingURL=brace-expressions.js.map
|
||||
@@ -0,0 +1,714 @@
|
||||
/**
|
||||
* Towered extension fields.
|
||||
* Rather than implementing a massive 12th-degree extension directly, it is more efficient
|
||||
* to build it up from smaller extensions: a tower of extensions.
|
||||
*
|
||||
* For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension,
|
||||
* on top of a cubic (degree three) extension, on top of a quadratic extension of Fp.
|
||||
*
|
||||
* For more info: "Pairings for beginners" by Costello, section 7.3.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { bitGet, bitLen, concatBytes, notImplemented } from "../utils.js";
|
||||
import * as mod from "./modular.js";
|
||||
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
||||
// prettier-ignore
|
||||
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
||||
function calcFrobeniusCoefficients(Fp, nonResidue, modulus, degree, num = 1, divisor) {
|
||||
const _divisor = BigInt(divisor === undefined ? degree : divisor);
|
||||
const towerModulus = modulus ** BigInt(degree);
|
||||
const res = [];
|
||||
for (let i = 0; i < num; i++) {
|
||||
const a = BigInt(i + 1);
|
||||
const powers = [];
|
||||
for (let j = 0, qPower = _1n; j < degree; j++) {
|
||||
const power = ((a * qPower - a) / _divisor) % towerModulus;
|
||||
powers.push(Fp.pow(nonResidue, power));
|
||||
qPower *= modulus;
|
||||
}
|
||||
res.push(powers);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// This works same at least for bls12-381, bn254 and bls12-377
|
||||
export function psiFrobenius(Fp, Fp2, base) {
|
||||
// GLV endomorphism Ψ(P)
|
||||
const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n); // u^((p-1)/3)
|
||||
const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n); // u^((p-1)/2)
|
||||
function psi(x, y) {
|
||||
// This x10 faster than previous version in bls12-381
|
||||
const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X);
|
||||
const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y);
|
||||
return [x2, y2];
|
||||
}
|
||||
// Ψ²(P) endomorphism (psi2(x) = psi(psi(x)))
|
||||
const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n); // u^((p^2 - 1)/3)
|
||||
// This equals -1, which causes y to be Fp2.neg(y).
|
||||
// But not sure if there are case when this is not true?
|
||||
const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n); // u^((p^2 - 1)/3)
|
||||
if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE)))
|
||||
throw new Error('psiFrobenius: PSI2_Y!==-1');
|
||||
function psi2(x, y) {
|
||||
return [Fp2.mul(x, PSI2_X), Fp2.neg(y)];
|
||||
}
|
||||
// Map points
|
||||
const mapAffine = (fn) => (c, P) => {
|
||||
const affine = P.toAffine();
|
||||
const p = fn(affine.x, affine.y);
|
||||
return c.fromAffine({ x: p[0], y: p[1] });
|
||||
};
|
||||
const G2psi = mapAffine(psi);
|
||||
const G2psi2 = mapAffine(psi2);
|
||||
return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y };
|
||||
}
|
||||
const Fp2fromBigTuple = (Fp, tuple) => {
|
||||
if (tuple.length !== 2)
|
||||
throw new Error('invalid tuple');
|
||||
const fps = tuple.map((n) => Fp.create(n));
|
||||
return { c0: fps[0], c1: fps[1] };
|
||||
};
|
||||
class _Field2 {
|
||||
constructor(Fp, opts = {}) {
|
||||
this.MASK = _1n;
|
||||
const ORDER = Fp.ORDER;
|
||||
const FP2_ORDER = ORDER * ORDER;
|
||||
this.Fp = Fp;
|
||||
this.ORDER = FP2_ORDER;
|
||||
this.BITS = bitLen(FP2_ORDER);
|
||||
this.BYTES = Math.ceil(bitLen(FP2_ORDER) / 8);
|
||||
this.isLE = Fp.isLE;
|
||||
this.ZERO = { c0: Fp.ZERO, c1: Fp.ZERO };
|
||||
this.ONE = { c0: Fp.ONE, c1: Fp.ZERO };
|
||||
this.Fp_NONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1));
|
||||
this.Fp_div2 = Fp.div(Fp.ONE, _2n); // 1/2
|
||||
this.NONRESIDUE = Fp2fromBigTuple(Fp, opts.FP2_NONRESIDUE);
|
||||
// const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE);
|
||||
this.FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, this.Fp_NONRESIDUE, Fp.ORDER, 2)[0];
|
||||
this.mulByB = opts.Fp2mulByB;
|
||||
Object.seal(this);
|
||||
}
|
||||
fromBigTuple(tuple) {
|
||||
return Fp2fromBigTuple(this.Fp, tuple);
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1 }) {
|
||||
function isValidC(num, ORDER) {
|
||||
return typeof num === 'bigint' && _0n <= num && num < ORDER;
|
||||
}
|
||||
return isValidC(c0, this.ORDER) && isValidC(c1, this.ORDER);
|
||||
}
|
||||
is0({ c0, c1 }) {
|
||||
return this.Fp.is0(c0) && this.Fp.is0(c1);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
eql({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
return this.Fp.eql(c0, r0) && this.Fp.eql(c1, r1);
|
||||
}
|
||||
neg({ c0, c1 }) {
|
||||
return { c0: this.Fp.neg(c0), c1: this.Fp.neg(c1) };
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
// Normalized
|
||||
add(f1, f2) {
|
||||
const { c0, c1 } = f1;
|
||||
const { c0: r0, c1: r1 } = f2;
|
||||
return {
|
||||
c0: this.Fp.add(c0, r0),
|
||||
c1: this.Fp.add(c1, r1),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
return {
|
||||
c0: this.Fp.sub(c0, r0),
|
||||
c1: this.Fp.sub(c1, r1),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1 }, rhs) {
|
||||
const { Fp } = this;
|
||||
if (typeof rhs === 'bigint')
|
||||
return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) };
|
||||
// (a+bi)(c+di) = (ac−bd) + (ad+bc)i
|
||||
const { c0: r0, c1: r1 } = rhs;
|
||||
let t1 = Fp.mul(c0, r0); // c0 * o0
|
||||
let t2 = Fp.mul(c1, r1); // c1 * o1
|
||||
// (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i
|
||||
const o0 = Fp.sub(t1, t2);
|
||||
const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2));
|
||||
return { c0: o0, c1: o1 };
|
||||
}
|
||||
sqr({ c0, c1 }) {
|
||||
const { Fp } = this;
|
||||
const a = Fp.add(c0, c1);
|
||||
const b = Fp.sub(c0, c1);
|
||||
const c = Fp.add(c0, c0);
|
||||
return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) };
|
||||
}
|
||||
// NonNormalized stuff
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
// Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
|
||||
div(lhs, rhs) {
|
||||
const { Fp } = this;
|
||||
// @ts-ignore
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
inv({ c0: a, c1: b }) {
|
||||
// We wish to find the multiplicative inverse of a nonzero
|
||||
// element a + bu in Fp2. We leverage an identity
|
||||
//
|
||||
// (a + bu)(a - bu) = a² + b²
|
||||
//
|
||||
// which holds because u² = -1. This can be rewritten as
|
||||
//
|
||||
// (a + bu)(a - bu)/(a² + b²) = 1
|
||||
//
|
||||
// because a² + b² = 0 has no nonzero solutions for (a, b).
|
||||
// This gives that (a - bu)/(a² + b²) is the inverse
|
||||
// of (a + bu). Importantly, this can be computing using
|
||||
// only a single inversion in Fp.
|
||||
const { Fp } = this;
|
||||
const factor = Fp.inv(Fp.create(a * a + b * b));
|
||||
return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
|
||||
}
|
||||
sqrt(num) {
|
||||
// This is generic for all quadratic extensions (Fp2)
|
||||
const { Fp } = this;
|
||||
const Fp2 = this;
|
||||
const { c0, c1 } = num;
|
||||
if (Fp.is0(c1)) {
|
||||
// if c0 is quadratic residue
|
||||
if (mod.FpLegendre(Fp, c0) === 1)
|
||||
return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO });
|
||||
else
|
||||
return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, this.Fp_NONRESIDUE)) });
|
||||
}
|
||||
const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), this.Fp_NONRESIDUE)));
|
||||
let d = Fp.mul(Fp.add(a, c0), this.Fp_div2);
|
||||
const legendre = mod.FpLegendre(Fp, d);
|
||||
// -1, Quadratic non residue
|
||||
if (legendre === -1)
|
||||
d = Fp.sub(d, a);
|
||||
const a0 = Fp.sqrt(d);
|
||||
const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, this.Fp_div2), a0) });
|
||||
if (!Fp2.eql(Fp2.sqr(candidateSqrt), num))
|
||||
throw new Error('Cannot find square root');
|
||||
// Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num
|
||||
const x1 = candidateSqrt;
|
||||
const x2 = Fp2.neg(x1);
|
||||
const { re: re1, im: im1 } = Fp2.reim(x1);
|
||||
const { re: re2, im: im2 } = Fp2.reim(x2);
|
||||
if (im1 > im2 || (im1 === im2 && re1 > re2))
|
||||
return x1;
|
||||
return x2;
|
||||
}
|
||||
// Same as sgn0_m_eq_2 in RFC 9380
|
||||
isOdd(x) {
|
||||
const { re: x0, im: x1 } = this.reim(x);
|
||||
const sign_0 = x0 % _2n;
|
||||
const zero_0 = x0 === _0n;
|
||||
const sign_1 = x1 % _2n;
|
||||
return BigInt(sign_0 || (zero_0 && sign_1)) == _1n;
|
||||
}
|
||||
// Bytes util
|
||||
fromBytes(b) {
|
||||
const { Fp } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
|
||||
}
|
||||
toBytes({ c0, c1 }) {
|
||||
return concatBytes(this.Fp.toBytes(c0), this.Fp.toBytes(c1));
|
||||
}
|
||||
cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
|
||||
return {
|
||||
c0: this.Fp.cmov(c0, r0, c),
|
||||
c1: this.Fp.cmov(c1, r1, c),
|
||||
};
|
||||
}
|
||||
reim({ c0, c1 }) {
|
||||
return { re: c0, im: c1 };
|
||||
}
|
||||
Fp4Square(a, b) {
|
||||
const Fp2 = this;
|
||||
const a2 = Fp2.sqr(a);
|
||||
const b2 = Fp2.sqr(b);
|
||||
return {
|
||||
first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
|
||||
second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
|
||||
};
|
||||
}
|
||||
// multiply by u + 1
|
||||
mulByNonresidue({ c0, c1 }) {
|
||||
return this.mul({ c0, c1 }, this.NONRESIDUE);
|
||||
}
|
||||
frobeniusMap({ c0, c1 }, power) {
|
||||
return {
|
||||
c0,
|
||||
c1: this.Fp.mul(c1, this.FROBENIUS_COEFFICIENTS[power % 2]),
|
||||
};
|
||||
}
|
||||
}
|
||||
class _Field6 {
|
||||
constructor(Fp2) {
|
||||
this.MASK = _1n;
|
||||
this.Fp2 = Fp2;
|
||||
this.ORDER = Fp2.ORDER; // TODO: unused, but need to verify
|
||||
this.BITS = 3 * Fp2.BITS;
|
||||
this.BYTES = 3 * Fp2.BYTES;
|
||||
this.isLE = Fp2.isLE;
|
||||
this.ZERO = { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO };
|
||||
this.ONE = { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO };
|
||||
const { Fp } = Fp2;
|
||||
const frob = calcFrobeniusCoefficients(Fp2, Fp2.NONRESIDUE, Fp.ORDER, 6, 2, 3);
|
||||
this.FROBENIUS_COEFFICIENTS_1 = frob[0];
|
||||
this.FROBENIUS_COEFFICIENTS_2 = frob[1];
|
||||
Object.seal(this);
|
||||
}
|
||||
add({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.add(c0, r0),
|
||||
c1: Fp2.add(c1, r1),
|
||||
c2: Fp2.add(c2, r2),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.sub(c0, r0),
|
||||
c1: Fp2.sub(c1, r1),
|
||||
c2: Fp2.sub(c2, r2),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1, c2 }, rhs) {
|
||||
const { Fp2 } = this;
|
||||
if (typeof rhs === 'bigint') {
|
||||
return {
|
||||
c0: Fp2.mul(c0, rhs),
|
||||
c1: Fp2.mul(c1, rhs),
|
||||
c2: Fp2.mul(c2, rhs),
|
||||
};
|
||||
}
|
||||
const { c0: r0, c1: r1, c2: r2 } = rhs;
|
||||
const t0 = Fp2.mul(c0, r0); // c0 * o0
|
||||
const t1 = Fp2.mul(c1, r1); // c1 * o1
|
||||
const t2 = Fp2.mul(c2, r2); // c2 * o2
|
||||
return {
|
||||
// t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
|
||||
c0: Fp2.add(t0, Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2)))),
|
||||
// (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
|
||||
c1: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), Fp2.mulByNonresidue(t2)),
|
||||
// T1 + (c0 + c2) * (r0 + r2) - T0 + T2
|
||||
c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)),
|
||||
};
|
||||
}
|
||||
sqr({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.sqr(c0); // c0²
|
||||
let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n); // 2 * c0 * c1
|
||||
let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n); // 2 * c1 * c2
|
||||
let t4 = Fp2.sqr(c2); // c2²
|
||||
return {
|
||||
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
|
||||
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1
|
||||
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
|
||||
c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),
|
||||
};
|
||||
}
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2);
|
||||
}
|
||||
is0({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
neg({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return { c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) };
|
||||
}
|
||||
eql({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2);
|
||||
}
|
||||
sqrt(_) {
|
||||
return notImplemented();
|
||||
}
|
||||
// Do we need division by bigint at all? Should be done via order:
|
||||
div(lhs, rhs) {
|
||||
const { Fp2 } = this;
|
||||
const { Fp } = Fp2;
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
inv({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))); // c0² - c2 * c1 * (u + 1)
|
||||
let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)); // c2² * (u + 1) - c0 * c1
|
||||
let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
|
||||
// 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
|
||||
let t4 = Fp2.inv(Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)));
|
||||
return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
|
||||
}
|
||||
// Bytes utils
|
||||
fromBytes(b) {
|
||||
const { Fp2 } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
const B2 = Fp2.BYTES;
|
||||
return {
|
||||
c0: Fp2.fromBytes(b.subarray(0, B2)),
|
||||
c1: Fp2.fromBytes(b.subarray(B2, B2 * 2)),
|
||||
c2: Fp2.fromBytes(b.subarray(2 * B2)),
|
||||
};
|
||||
}
|
||||
toBytes({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2));
|
||||
}
|
||||
cmov({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.cmov(c0, r0, c),
|
||||
c1: Fp2.cmov(c1, r1, c),
|
||||
c2: Fp2.cmov(c2, r2, c),
|
||||
};
|
||||
}
|
||||
fromBigSix(t) {
|
||||
const { Fp2 } = this;
|
||||
if (!Array.isArray(t) || t.length !== 6)
|
||||
throw new Error('invalid Fp6 usage');
|
||||
return {
|
||||
c0: Fp2.fromBigTuple(t.slice(0, 2)),
|
||||
c1: Fp2.fromBigTuple(t.slice(2, 4)),
|
||||
c2: Fp2.fromBigTuple(t.slice(4, 6)),
|
||||
};
|
||||
}
|
||||
frobeniusMap({ c0, c1, c2 }, power) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.frobeniusMap(c0, power),
|
||||
c1: Fp2.mul(Fp2.frobeniusMap(c1, power), this.FROBENIUS_COEFFICIENTS_1[power % 6]),
|
||||
c2: Fp2.mul(Fp2.frobeniusMap(c2, power), this.FROBENIUS_COEFFICIENTS_2[power % 6]),
|
||||
};
|
||||
}
|
||||
mulByFp2({ c0, c1, c2 }, rhs) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.mul(c0, rhs),
|
||||
c1: Fp2.mul(c1, rhs),
|
||||
c2: Fp2.mul(c2, rhs),
|
||||
};
|
||||
}
|
||||
mulByNonresidue({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return { c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 };
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul1({ c0, c1, c2 }, b1) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)),
|
||||
c1: Fp2.mul(c0, b1),
|
||||
c2: Fp2.mul(c1, b1),
|
||||
};
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul01({ c0, c1, c2 }, b0, b1) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.mul(c0, b0); // c0 * b0
|
||||
let t1 = Fp2.mul(c1, b1); // c1 * b1
|
||||
return {
|
||||
// ((c1 + c2) * b1 - T1) * (u + 1) + T0
|
||||
c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0),
|
||||
// (b0 + b1) * (c0 + c1) - T0 - T1
|
||||
c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1),
|
||||
// (c0 + c2) * b0 - T0 + T1
|
||||
c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1),
|
||||
};
|
||||
}
|
||||
}
|
||||
class _Field12 {
|
||||
constructor(Fp6, opts) {
|
||||
this.MASK = _1n;
|
||||
const { Fp2 } = Fp6;
|
||||
const { Fp } = Fp2;
|
||||
this.Fp6 = Fp6;
|
||||
this.ORDER = Fp2.ORDER; // TODO: verify if it's unuesd
|
||||
this.BITS = 2 * Fp6.BITS;
|
||||
this.BYTES = 2 * Fp6.BYTES;
|
||||
this.isLE = Fp6.isLE;
|
||||
this.ZERO = { c0: Fp6.ZERO, c1: Fp6.ZERO };
|
||||
this.ONE = { c0: Fp6.ONE, c1: Fp6.ZERO };
|
||||
this.FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp2, Fp2.NONRESIDUE, Fp.ORDER, 12, 1, 6)[0];
|
||||
this.X_LEN = opts.X_LEN;
|
||||
this.finalExponentiate = opts.Fp12finalExponentiate;
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.isValid(c0) && Fp6.isValid(c1);
|
||||
}
|
||||
is0({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.is0(c0) && Fp6.is0(c1);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
neg({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return { c0: Fp6.neg(c0), c1: Fp6.neg(c1) };
|
||||
}
|
||||
eql({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.eql(c0, r0) && Fp6.eql(c1, r1);
|
||||
}
|
||||
sqrt(_) {
|
||||
notImplemented();
|
||||
}
|
||||
inv({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))); // 1 / (c0² - c1² * v)
|
||||
return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
|
||||
}
|
||||
div(lhs, rhs) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { Fp } = Fp2;
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
// Normalized
|
||||
add({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.add(c0, r0),
|
||||
c1: Fp6.add(c1, r1),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.sub(c0, r0),
|
||||
c1: Fp6.sub(c1, r1),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1 }, rhs) {
|
||||
const { Fp6 } = this;
|
||||
if (typeof rhs === 'bigint')
|
||||
return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) };
|
||||
let { c0: r0, c1: r1 } = rhs;
|
||||
let t1 = Fp6.mul(c0, r0); // c0 * r0
|
||||
let t2 = Fp6.mul(c1, r1); // c1 * r1
|
||||
return {
|
||||
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v
|
||||
// (c0 + c1) * (r0 + r1) - (T1 + T2)
|
||||
c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),
|
||||
};
|
||||
}
|
||||
sqr({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
let ab = Fp6.mul(c0, c1); // c0 * c1
|
||||
return {
|
||||
// (c1 * v + c0) * (c0 + c1) - AB - AB * v
|
||||
c0: Fp6.sub(Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), Fp6.mulByNonresidue(ab)),
|
||||
c1: Fp6.add(ab, ab),
|
||||
}; // AB + AB
|
||||
}
|
||||
// NonNormalized stuff
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
// Bytes utils
|
||||
fromBytes(b) {
|
||||
const { Fp6 } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
return {
|
||||
c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)),
|
||||
c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
|
||||
};
|
||||
}
|
||||
toBytes({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1));
|
||||
}
|
||||
cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.cmov(c0, r0, c),
|
||||
c1: Fp6.cmov(c1, r1, c),
|
||||
};
|
||||
}
|
||||
// Utils
|
||||
// toString() {
|
||||
// return '' + 'Fp12(' + this.c0 + this.c1 + '* w');
|
||||
// },
|
||||
// fromTuple(c: [Fp6, Fp6]) {
|
||||
// return new Fp12(...c);
|
||||
// }
|
||||
fromBigTwelve(t) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.fromBigSix(t.slice(0, 6)),
|
||||
c1: Fp6.fromBigSix(t.slice(6, 12)),
|
||||
};
|
||||
}
|
||||
// Raises to q**i -th power
|
||||
frobeniusMap(lhs, power) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power);
|
||||
const coeff = this.FROBENIUS_COEFFICIENTS[power % 12];
|
||||
return {
|
||||
c0: Fp6.frobeniusMap(lhs.c0, power),
|
||||
c1: Fp6.create({
|
||||
c0: Fp2.mul(c0, coeff),
|
||||
c1: Fp2.mul(c1, coeff),
|
||||
c2: Fp2.mul(c2, coeff),
|
||||
}),
|
||||
};
|
||||
}
|
||||
mulByFp2({ c0, c1 }, rhs) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.mulByFp2(c0, rhs),
|
||||
c1: Fp6.mulByFp2(c1, rhs),
|
||||
};
|
||||
}
|
||||
conjugate({ c0, c1 }) {
|
||||
return { c0, c1: this.Fp6.neg(c1) };
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul014({ c0, c1 }, o0, o1, o4) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
let t0 = Fp6.mul01(c0, o0, o1);
|
||||
let t1 = Fp6.mul1(c1, o4);
|
||||
return {
|
||||
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
|
||||
// (c1 + c0) * [o0, o1+o4] - T0 - T1
|
||||
c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),
|
||||
};
|
||||
}
|
||||
mul034({ c0, c1 }, o0, o3, o4) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const a = Fp6.create({
|
||||
c0: Fp2.mul(c0.c0, o0),
|
||||
c1: Fp2.mul(c0.c1, o0),
|
||||
c2: Fp2.mul(c0.c2, o0),
|
||||
});
|
||||
const b = Fp6.mul01(c1, o3, o4);
|
||||
const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4);
|
||||
return {
|
||||
c0: Fp6.add(Fp6.mulByNonresidue(b), a),
|
||||
c1: Fp6.sub(e, Fp6.add(a, b)),
|
||||
};
|
||||
}
|
||||
// A cyclotomic group is a subgroup of Fp^n defined by
|
||||
// GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
|
||||
// The result of any pairing is in a cyclotomic subgroup
|
||||
// https://eprint.iacr.org/2009/565.pdf
|
||||
// https://eprint.iacr.org/2010/354.pdf
|
||||
_cyclotomicSquare({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
|
||||
const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
|
||||
const { first: t3, second: t4 } = Fp2.Fp4Square(c0c0, c1c1);
|
||||
const { first: t5, second: t6 } = Fp2.Fp4Square(c1c0, c0c2);
|
||||
const { first: t7, second: t8 } = Fp2.Fp4Square(c0c1, c1c2);
|
||||
const t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
|
||||
return {
|
||||
c0: Fp6.create({
|
||||
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
|
||||
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
|
||||
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
|
||||
}), // 2 * (T7 - c0c2) + T7
|
||||
c1: Fp6.create({
|
||||
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
|
||||
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
|
||||
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
|
||||
}),
|
||||
}; // 2 * (T6 + c1c2) + T6
|
||||
}
|
||||
// https://eprint.iacr.org/2009/565.pdf
|
||||
_cyclotomicExp(num, n) {
|
||||
let z = this.ONE;
|
||||
for (let i = this.X_LEN - 1; i >= 0; i--) {
|
||||
z = this._cyclotomicSquare(z);
|
||||
if (bitGet(n, i))
|
||||
z = this.mul(z, num);
|
||||
}
|
||||
return z;
|
||||
}
|
||||
}
|
||||
export function tower12(opts) {
|
||||
const Fp = mod.Field(opts.ORDER);
|
||||
const Fp2 = new _Field2(Fp, opts);
|
||||
const Fp6 = new _Field6(Fp2);
|
||||
const Fp12 = new _Field12(Fp6, opts);
|
||||
return { Fp, Fp2, Fp6, Fp12 };
|
||||
}
|
||||
//# sourceMappingURL=tower.js.map
|
||||
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
var _check_private_redeclaration = require("./_check_private_redeclaration.cjs");
|
||||
|
||||
function _class_private_method_init(obj, privateSet) {
|
||||
_check_private_redeclaration._(obj, privateSet);
|
||||
privateSet.add(obj);
|
||||
}
|
||||
exports._ = _class_private_method_init;
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npm test
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,126 @@
|
||||
import type { ProjectServiceAndMetadata } from '@typescript-eslint/project-service';
|
||||
import type * as ts from 'typescript';
|
||||
import type { CanonicalPath } from '../create-program/shared';
|
||||
import type { TSESTree } from '../ts-estree';
|
||||
import type { CacheLike } from './ExpiringCache';
|
||||
type DebugModule = 'eslint' | 'typescript' | 'typescript-eslint';
|
||||
declare module 'typescript' {
|
||||
enum JSDocParsingMode {
|
||||
}
|
||||
}
|
||||
declare module 'typescript/lib/tsserverlibrary' {
|
||||
enum JSDocParsingMode {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Internal settings used by the parser to run on a file.
|
||||
*/
|
||||
export interface MutableParseSettings {
|
||||
/**
|
||||
* Prevents the parser from throwing an error if it receives an invalid AST from TypeScript.
|
||||
*/
|
||||
allowInvalidAST: boolean;
|
||||
/**
|
||||
* Code of the file being parsed, or raw source file containing it.
|
||||
*/
|
||||
code: string | ts.SourceFile;
|
||||
/**
|
||||
* Full text of the file being parsed.
|
||||
*/
|
||||
codeFullText: string;
|
||||
/**
|
||||
* Whether the `comment` parse option is enabled.
|
||||
*/
|
||||
comment: boolean;
|
||||
/**
|
||||
* If the `comment` parse option is enabled, retrieved comments.
|
||||
*/
|
||||
comments: TSESTree.Comment[];
|
||||
/**
|
||||
* Which debug areas should be logged.
|
||||
*/
|
||||
debugLevel: Set<DebugModule>;
|
||||
/**
|
||||
* Whether to error if TypeScript reports a semantic or syntactic error diagnostic.
|
||||
*/
|
||||
errorOnTypeScriptSyntacticAndSemanticIssues: boolean;
|
||||
/**
|
||||
* Whether to error if an unknown AST node type is encountered.
|
||||
*/
|
||||
errorOnUnknownASTType: boolean;
|
||||
/**
|
||||
* Any non-standard file extensions which will be parsed.
|
||||
*/
|
||||
extraFileExtensions: string[];
|
||||
/**
|
||||
* Path of the file being parsed.
|
||||
*/
|
||||
filePath: string;
|
||||
/**
|
||||
* Sets the external module indicator on the source file.
|
||||
* Used by Typescript to determine if a sourceFile is an external module.
|
||||
*
|
||||
* needed to always parsing `mjs`/`mts` files as ESM
|
||||
*/
|
||||
setExternalModuleIndicator?: (file: ts.SourceFile) => void;
|
||||
/**
|
||||
* JSDoc parsing style to pass through to TypeScript
|
||||
*/
|
||||
jsDocParsingMode: ts.JSDocParsingMode;
|
||||
/**
|
||||
* Whether parsing of JSX is enabled.
|
||||
*
|
||||
* @remarks The applicable file extension is still required.
|
||||
*/
|
||||
jsx: boolean;
|
||||
/**
|
||||
* Whether to add `loc` information to each node.
|
||||
*/
|
||||
loc: boolean;
|
||||
/**
|
||||
* Log function, if not `console.log`.
|
||||
*/
|
||||
log: (message: string) => void;
|
||||
/**
|
||||
* Whether two-way AST node maps are preserved during the AST conversion process.
|
||||
*/
|
||||
preserveNodeMaps?: boolean;
|
||||
/**
|
||||
* One or more instances of TypeScript Program objects to be used for type information.
|
||||
*/
|
||||
programs: Iterable<ts.Program> | null;
|
||||
/**
|
||||
* Normalized paths to provided project paths.
|
||||
*/
|
||||
projects: ReadonlyMap<CanonicalPath, string>;
|
||||
/**
|
||||
* TypeScript server to power program creation.
|
||||
*/
|
||||
projectService: ProjectServiceAndMetadata | undefined;
|
||||
/**
|
||||
* Whether to add the `range` property to AST nodes.
|
||||
*/
|
||||
range: boolean;
|
||||
/**
|
||||
* Whether this is part of a single run, rather than a long-running process.
|
||||
*/
|
||||
singleRun: boolean;
|
||||
/**
|
||||
* Whether deprecated AST properties should skip calling console.warn on accesses.
|
||||
*/
|
||||
suppressDeprecatedPropertyWarnings: boolean;
|
||||
/**
|
||||
* If the `tokens` parse option is enabled, retrieved tokens.
|
||||
*/
|
||||
tokens: TSESTree.Token[] | null;
|
||||
/**
|
||||
* Caches searches for TSConfigs from project directories.
|
||||
*/
|
||||
tsconfigMatchCache: CacheLike<string, string>;
|
||||
/**
|
||||
* The absolute path to the root directory for all provided `project`s.
|
||||
*/
|
||||
tsconfigRootDir: string;
|
||||
}
|
||||
export type ParseSettings = Readonly<MutableParseSettings>;
|
||||
export {};
|
||||
@@ -0,0 +1,91 @@
|
||||
// Type definitions for non-npm package Node.js 12.20
|
||||
// Project: https://nodejs.org/
|
||||
// Definitions by: Microsoft TypeScript <https://github.com/Microsoft>
|
||||
// DefinitelyTyped <https://github.com/DefinitelyTyped>
|
||||
// Alberto Schiabel <https://github.com/jkomyno>
|
||||
// Alvis HT Tang <https://github.com/alvis>
|
||||
// Andrew Makarov <https://github.com/r3nya>
|
||||
// Benjamin Toueg <https://github.com/btoueg>
|
||||
// Chigozirim C. <https://github.com/smac89>
|
||||
// David Junger <https://github.com/touffy>
|
||||
// Deividas Bakanas <https://github.com/DeividasBakanas>
|
||||
// Eugene Y. Q. Shen <https://github.com/eyqs>
|
||||
// Hannes Magnusson <https://github.com/Hannes-Magnusson-CK>
|
||||
// Hoàng Văn Khải <https://github.com/KSXGitHub>
|
||||
// Huw <https://github.com/hoo29>
|
||||
// Kelvin Jin <https://github.com/kjin>
|
||||
// Klaus Meinhardt <https://github.com/ajafff>
|
||||
// Lishude <https://github.com/islishude>
|
||||
// Mariusz Wiktorczyk <https://github.com/mwiktorczyk>
|
||||
// Mohsen Azimi <https://github.com/mohsen1>
|
||||
// Nicolas Even <https://github.com/n-e>
|
||||
// Nikita Galkin <https://github.com/galkin>
|
||||
// Parambir Singh <https://github.com/parambirs>
|
||||
// Sebastian Silbermann <https://github.com/eps1lon>
|
||||
// Simon Schick <https://github.com/SimonSchick>
|
||||
// Thomas den Hollander <https://github.com/ThomasdenH>
|
||||
// Wilco Bakker <https://github.com/WilcoBakker>
|
||||
// wwwy3y3 <https://github.com/wwwy3y3>
|
||||
// Zane Hannan AU <https://github.com/ZaneHannanAU>
|
||||
// Samuel Ainsworth <https://github.com/samuela>
|
||||
// Kyle Uehlein <https://github.com/kuehlein>
|
||||
// Thanik Bhongbhibhat <https://github.com/bhongy>
|
||||
// Marcin Kopacz <https://github.com/chyzwar>
|
||||
// Trivikram Kamat <https://github.com/trivikr>
|
||||
// Junxiao Shi <https://github.com/yoursunny>
|
||||
// Ilia Baryshnikov <https://github.com/qwelias>
|
||||
// ExE Boss <https://github.com/ExE-Boss>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
// NOTE: These definitions support NodeJS and TypeScript 3.7.
|
||||
// This isn't strictly needed since 3.7 has the assert module, but this way we're consistent.
|
||||
// Typically type modifications should be made in base.d.ts instead of here
|
||||
|
||||
// Reference required types from the default lib:
|
||||
/// <reference lib="es2018" />
|
||||
/// <reference lib="esnext.asynciterable" />
|
||||
/// <reference lib="esnext.intl" />
|
||||
/// <reference lib="esnext.bigint" />
|
||||
|
||||
/// <reference path="assert.d.ts" />
|
||||
/// <reference path="globals.d.ts" />
|
||||
/// <reference path="async_hooks.d.ts" />
|
||||
/// <reference path="buffer.d.ts" />
|
||||
/// <reference path="child_process.d.ts" />
|
||||
/// <reference path="cluster.d.ts" />
|
||||
/// <reference path="console.d.ts" />
|
||||
/// <reference path="constants.d.ts" />
|
||||
/// <reference path="crypto.d.ts" />
|
||||
/// <reference path="dgram.d.ts" />
|
||||
/// <reference path="dns.d.ts" />
|
||||
/// <reference path="domain.d.ts" />
|
||||
/// <reference path="events.d.ts" />
|
||||
/// <reference path="fs.d.ts" />
|
||||
/// <reference path="http.d.ts" />
|
||||
/// <reference path="http2.d.ts" />
|
||||
/// <reference path="https.d.ts" />
|
||||
/// <reference path="inspector.d.ts" />
|
||||
/// <reference path="module.d.ts" />
|
||||
/// <reference path="net.d.ts" />
|
||||
/// <reference path="os.d.ts" />
|
||||
/// <reference path="path.d.ts" />
|
||||
/// <reference path="perf_hooks.d.ts" />
|
||||
/// <reference path="process.d.ts" />
|
||||
/// <reference path="punycode.d.ts" />
|
||||
/// <reference path="querystring.d.ts" />
|
||||
/// <reference path="readline.d.ts" />
|
||||
/// <reference path="repl.d.ts" />
|
||||
/// <reference path="stream.d.ts" />
|
||||
/// <reference path="string_decoder.d.ts" />
|
||||
/// <reference path="timers.d.ts" />
|
||||
/// <reference path="tls.d.ts" />
|
||||
/// <reference path="trace_events.d.ts" />
|
||||
/// <reference path="tty.d.ts" />
|
||||
/// <reference path="url.d.ts" />
|
||||
/// <reference path="util.d.ts" />
|
||||
/// <reference path="v8.d.ts" />
|
||||
/// <reference path="vm.d.ts" />
|
||||
/// <reference path="wasi.d.ts" />
|
||||
/// <reference path="worker_threads.d.ts" />
|
||||
/// <reference path="zlib.d.ts" />
|
||||
/// <reference path="globals.global.d.ts" />
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 InfluxData
|
||||
|
||||
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,35 @@
|
||||
{
|
||||
"keys-while": {
|
||||
"name": "keys-while",
|
||||
"browser": "Safari 9.1.2 (Mac OS X 10.11.6)",
|
||||
"suite": "iter",
|
||||
"hz": 28986.560290298727,
|
||||
"success": true,
|
||||
"fastest": true,
|
||||
"rme": 0.01955387244622322,
|
||||
"rhz": 1,
|
||||
"sampleSize": 163
|
||||
},
|
||||
"keys-for": {
|
||||
"name": "keys-for",
|
||||
"browser": "Safari 9.1.2 (Mac OS X 10.11.6)",
|
||||
"suite": "iter",
|
||||
"hz": 28441.864683475418,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.015457331597656216,
|
||||
"rhz": 0.9812086842533846,
|
||||
"sampleSize": 168
|
||||
},
|
||||
"incr-for": {
|
||||
"name": "incr-for",
|
||||
"browser": "Safari 9.1.2 (Mac OS X 10.11.6)",
|
||||
"suite": "iter",
|
||||
"hz": 14812.329514457171,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.01749261318544788,
|
||||
"rhz": 0.5110068033637847,
|
||||
"sampleSize": 171
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
'use strict'
|
||||
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
|
||||
const { parse, serialize } = require('pg-protocol')
|
||||
const stream = require('./stream')
|
||||
const { getStream } = stream
|
||||
|
||||
const flushBuffer = serialize.flush()
|
||||
const syncBuffer = serialize.sync()
|
||||
const endBuffer = serialize.end()
|
||||
|
||||
// TODO(bmc) support binary mode at some point
|
||||
class Connection extends EventEmitter {
|
||||
constructor(config) {
|
||||
super()
|
||||
config = config || {}
|
||||
|
||||
this.stream = config.stream || getStream(config.ssl)
|
||||
if (typeof this.stream === 'function') {
|
||||
this.stream = this.stream(config)
|
||||
}
|
||||
|
||||
this._keepAlive = config.keepAlive
|
||||
this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis
|
||||
this.parsedStatements = {}
|
||||
this.submittedNamedStatements = {}
|
||||
this.ssl = config.ssl || false
|
||||
this.sslNegotiation = config.sslNegotiation || 'postgres'
|
||||
this._ending = false
|
||||
this._emitMessage = false
|
||||
const self = this
|
||||
this.on('newListener', function (eventName) {
|
||||
if (eventName === 'message') {
|
||||
self._emitMessage = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
connect(port, host) {
|
||||
const self = this
|
||||
|
||||
this._connecting = true
|
||||
this.stream.setNoDelay(true)
|
||||
this.stream.connect(port, host)
|
||||
|
||||
this.stream.once('connect', function () {
|
||||
if (self._keepAlive) {
|
||||
self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis)
|
||||
}
|
||||
self.emit('connect')
|
||||
})
|
||||
|
||||
const reportStreamError = function (error) {
|
||||
// errors about disconnections should be ignored during disconnect
|
||||
if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) {
|
||||
return
|
||||
}
|
||||
self.emit('error', error)
|
||||
}
|
||||
this.stream.on('error', reportStreamError)
|
||||
|
||||
this.stream.on('close', function () {
|
||||
self.emit('end')
|
||||
})
|
||||
|
||||
if (!this.ssl) {
|
||||
return this.attachListeners(this.stream)
|
||||
}
|
||||
|
||||
// With direct SSL negotiation the TLS handshake starts immediately on the
|
||||
// raw socket, skipping the SSLRequest packet and the server's 'S'/'N' reply.
|
||||
if (this.sslNegotiation === 'direct') {
|
||||
return this.stream.once('connect', function () {
|
||||
self.upgradeToSSL(host, reportStreamError)
|
||||
})
|
||||
}
|
||||
|
||||
this.stream.once('data', function (buffer) {
|
||||
const responseCode = buffer.toString('utf8')
|
||||
switch (responseCode) {
|
||||
case 'S': // Server supports SSL connections, continue with a secure connection
|
||||
break
|
||||
case 'N': // Server does not support SSL connections
|
||||
self.stream.end()
|
||||
return self.emit('error', new Error('The server does not support SSL connections'))
|
||||
default:
|
||||
// Any other response byte, including 'E' (ErrorResponse) indicating a server error
|
||||
self.stream.end()
|
||||
return self.emit('error', new Error('There was an error establishing an SSL connection'))
|
||||
}
|
||||
self.upgradeToSSL(host, reportStreamError)
|
||||
})
|
||||
}
|
||||
|
||||
upgradeToSSL(host, reportStreamError) {
|
||||
const self = this
|
||||
const options = {
|
||||
socket: self.stream,
|
||||
}
|
||||
|
||||
if (self.ssl !== true) {
|
||||
Object.assign(options, self.ssl)
|
||||
|
||||
if ('key' in self.ssl) {
|
||||
options.key = self.ssl.key
|
||||
}
|
||||
}
|
||||
|
||||
// Direct SSL negotiation requires ALPN so the server can confirm it is
|
||||
// speaking the PostgreSQL protocol over the TLS connection.
|
||||
if (self.sslNegotiation === 'direct') {
|
||||
options.ALPNProtocols = ['postgresql']
|
||||
}
|
||||
|
||||
const net = require('net')
|
||||
if (net.isIP && net.isIP(host) === 0) {
|
||||
options.servername = host
|
||||
}
|
||||
try {
|
||||
self.stream = stream.getSecureStream(options)
|
||||
} catch (err) {
|
||||
return self.emit('error', err)
|
||||
}
|
||||
self.attachListeners(self.stream)
|
||||
self.stream.on('error', reportStreamError)
|
||||
|
||||
self.emit('sslconnect')
|
||||
}
|
||||
|
||||
attachListeners(stream) {
|
||||
parse(stream, (msg) => {
|
||||
const eventName = msg.name === 'error' ? 'errorMessage' : msg.name
|
||||
if (this._emitMessage) {
|
||||
this.emit('message', msg)
|
||||
}
|
||||
this.emit(eventName, msg)
|
||||
})
|
||||
}
|
||||
|
||||
requestSsl() {
|
||||
this.stream.write(serialize.requestSsl())
|
||||
}
|
||||
|
||||
startup(config) {
|
||||
this.stream.write(serialize.startup(config))
|
||||
}
|
||||
|
||||
cancel(processID, secretKey) {
|
||||
this._send(serialize.cancel(processID, secretKey))
|
||||
}
|
||||
|
||||
password(password) {
|
||||
this._send(serialize.password(password))
|
||||
}
|
||||
|
||||
sendSASLInitialResponseMessage(mechanism, initialResponse) {
|
||||
this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse))
|
||||
}
|
||||
|
||||
sendSCRAMClientFinalMessage(additionalData) {
|
||||
this._send(serialize.sendSCRAMClientFinalMessage(additionalData))
|
||||
}
|
||||
|
||||
_send(buffer) {
|
||||
if (!this.stream.writable) {
|
||||
return false
|
||||
}
|
||||
return this.stream.write(buffer)
|
||||
}
|
||||
|
||||
query(text) {
|
||||
this._send(serialize.query(text))
|
||||
}
|
||||
|
||||
// send parse message
|
||||
parse(query) {
|
||||
this._send(serialize.parse(query))
|
||||
}
|
||||
|
||||
// send bind message
|
||||
bind(config) {
|
||||
this._send(serialize.bind(config))
|
||||
}
|
||||
|
||||
// send execute message
|
||||
execute(config) {
|
||||
this._send(serialize.execute(config))
|
||||
}
|
||||
|
||||
flush() {
|
||||
if (this.stream.writable) {
|
||||
this.stream.write(flushBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
sync() {
|
||||
this._ending = true
|
||||
this._send(syncBuffer)
|
||||
}
|
||||
|
||||
ref() {
|
||||
this.stream.ref()
|
||||
}
|
||||
|
||||
unref() {
|
||||
this.stream.unref()
|
||||
}
|
||||
|
||||
end() {
|
||||
// 0x58 = 'X'
|
||||
this._ending = true
|
||||
if (!this._connecting || !this.stream.writable) {
|
||||
this.stream.end()
|
||||
return
|
||||
}
|
||||
return this.stream.write(endBuffer, () => {
|
||||
this.stream.end()
|
||||
})
|
||||
}
|
||||
|
||||
close(msg) {
|
||||
this._send(serialize.close(msg))
|
||||
}
|
||||
|
||||
describe(msg) {
|
||||
this._send(serialize.describe(msg))
|
||||
}
|
||||
|
||||
sendCopyFromChunk(chunk) {
|
||||
this._send(serialize.copyData(chunk))
|
||||
}
|
||||
|
||||
endCopyFrom() {
|
||||
this._send(serialize.copyDone())
|
||||
}
|
||||
|
||||
sendCopyFail(msg) {
|
||||
this._send(serialize.copyFail(msg))
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Connection
|
||||
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.esnext = void 0;
|
||||
const es2025_1 = require("./es2025");
|
||||
const esnext_array_1 = require("./esnext.array");
|
||||
const esnext_collection_1 = require("./esnext.collection");
|
||||
const esnext_date_1 = require("./esnext.date");
|
||||
const esnext_decorators_1 = require("./esnext.decorators");
|
||||
const esnext_disposable_1 = require("./esnext.disposable");
|
||||
const esnext_error_1 = require("./esnext.error");
|
||||
const esnext_intl_1 = require("./esnext.intl");
|
||||
const esnext_sharedmemory_1 = require("./esnext.sharedmemory");
|
||||
const esnext_temporal_1 = require("./esnext.temporal");
|
||||
const esnext_typedarrays_1 = require("./esnext.typedarrays");
|
||||
exports.esnext = {
|
||||
libs: [
|
||||
es2025_1.es2025,
|
||||
esnext_intl_1.esnext_intl,
|
||||
esnext_collection_1.esnext_collection,
|
||||
esnext_decorators_1.esnext_decorators,
|
||||
esnext_disposable_1.esnext_disposable,
|
||||
esnext_array_1.esnext_array,
|
||||
esnext_error_1.esnext_error,
|
||||
esnext_sharedmemory_1.esnext_sharedmemory,
|
||||
esnext_typedarrays_1.esnext_typedarrays,
|
||||
esnext_temporal_1.esnext_temporal,
|
||||
esnext_date_1.esnext_date,
|
||||
],
|
||||
variables: [],
|
||||
};
|
||||
@@ -0,0 +1,556 @@
|
||||
declare module "node:url" {
|
||||
import { Blob, NonSharedBuffer } from "node:buffer";
|
||||
import { ClientRequestArgs } from "node:http";
|
||||
import { ParsedUrlQuery, ParsedUrlQueryInput } from "node:querystring";
|
||||
// Input to `url.format`
|
||||
interface UrlObject {
|
||||
auth?: string | null | undefined;
|
||||
hash?: string | null | undefined;
|
||||
host?: string | null | undefined;
|
||||
hostname?: string | null | undefined;
|
||||
href?: string | null | undefined;
|
||||
pathname?: string | null | undefined;
|
||||
protocol?: string | null | undefined;
|
||||
search?: string | null | undefined;
|
||||
slashes?: boolean | null | undefined;
|
||||
port?: string | number | null | undefined;
|
||||
query?: string | null | ParsedUrlQueryInput | undefined;
|
||||
}
|
||||
// Output of `url.parse`
|
||||
interface Url {
|
||||
auth: string | null;
|
||||
hash: string | null;
|
||||
host: string | null;
|
||||
hostname: string | null;
|
||||
href: string;
|
||||
path: string | null;
|
||||
pathname: string | null;
|
||||
protocol: string | null;
|
||||
search: string | null;
|
||||
slashes: boolean | null;
|
||||
port: string | null;
|
||||
query: string | null | ParsedUrlQuery;
|
||||
}
|
||||
interface UrlWithParsedQuery extends Url {
|
||||
query: ParsedUrlQuery;
|
||||
}
|
||||
interface UrlWithStringQuery extends Url {
|
||||
query: string | null;
|
||||
}
|
||||
interface FileUrlToPathOptions {
|
||||
/**
|
||||
* `true` if the `path` should be return as a windows filepath, `false` for posix, and `undefined` for the system default.
|
||||
* @default undefined
|
||||
* @since v22.1.0
|
||||
*/
|
||||
windows?: boolean | undefined;
|
||||
}
|
||||
interface PathToFileUrlOptions {
|
||||
/**
|
||||
* `true` if the `path` should be return as a windows filepath, `false` for posix, and `undefined` for the system default.
|
||||
* @default undefined
|
||||
* @since v22.1.0
|
||||
*/
|
||||
windows?: boolean | undefined;
|
||||
}
|
||||
/**
|
||||
* The `url.parse()` method takes a URL string, parses it, and returns a URL
|
||||
* object.
|
||||
*
|
||||
* A `TypeError` is thrown if `urlString` is not a string.
|
||||
*
|
||||
* A `URIError` is thrown if the `auth` property is present but cannot be decoded.
|
||||
*
|
||||
* `url.parse()` uses a lenient, non-standard algorithm for parsing URL
|
||||
* strings. It is prone to security issues such as [host name spoofing](https://hackerone.com/reports/678487)
|
||||
* and incorrect handling of usernames and passwords. Do not use with untrusted
|
||||
* input. CVEs are not issued for `url.parse()` vulnerabilities. Use the
|
||||
* [WHATWG URL](https://nodejs.org/docs/latest-v26.x/api/url.html#the-whatwg-url-api) API instead, for example:
|
||||
*
|
||||
* ```js
|
||||
* function getURL(req) {
|
||||
* const proto = req.headers['x-forwarded-proto'] || 'https';
|
||||
* const host = req.headers['x-forwarded-host'] || req.headers.host || 'example.com';
|
||||
* return new URL(req.url || '/', `${proto}://${host}`);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The example above assumes well-formed headers are forwarded from a reverse
|
||||
* proxy to your Node.js server. If you are not using a reverse proxy, you should
|
||||
* use the example below:
|
||||
*
|
||||
* ```js
|
||||
* function getURL(req) {
|
||||
* return new URL(req.url || '/', 'https://example.com');
|
||||
* }
|
||||
* ```
|
||||
* @since v0.1.25
|
||||
* @deprecated Use the WHATWG URL API instead.
|
||||
* @param urlString The URL string to parse.
|
||||
* @param parseQueryString If `true`, the `query` property will always
|
||||
* be set to an object returned by the [`querystring`](https://nodejs.org/docs/latest-v26.x/api/querystring.html) module's `parse()`
|
||||
* method. If `false`, the `query` property on the returned URL object will be an
|
||||
* unparsed, undecoded string. **Default:** `false`.
|
||||
* @param slashesDenoteHost If `true`, the first token after the literal
|
||||
* string `//` and preceding the next `/` will be interpreted as the `host`.
|
||||
* For instance, given `//foo/bar`, the result would be
|
||||
* `{host: 'foo', pathname: '/bar'}` rather than `{pathname: '//foo/bar'}`.
|
||||
* **Default:** `false`.
|
||||
*/
|
||||
function parse(
|
||||
urlString: string,
|
||||
parseQueryString?: false,
|
||||
slashesDenoteHost?: boolean,
|
||||
): UrlWithStringQuery;
|
||||
function parse(urlString: string, parseQueryString: true, slashesDenoteHost?: boolean): UrlWithParsedQuery;
|
||||
function parse(urlString: string, parseQueryString: boolean, slashesDenoteHost?: boolean): Url;
|
||||
/**
|
||||
* The `url.format()` method returns a formatted URL string derived from `urlObject`.
|
||||
*
|
||||
* ```js
|
||||
* import url from 'node:url';
|
||||
* url.format({
|
||||
* protocol: 'https',
|
||||
* hostname: 'example.com',
|
||||
* pathname: '/some/path',
|
||||
* query: {
|
||||
* page: 1,
|
||||
* format: 'json',
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* // => 'https://example.com/some/path?page=1&format=json'
|
||||
* ```
|
||||
*
|
||||
* If `urlObject` is not an object or a string, `url.format()` will throw a `TypeError`.
|
||||
*
|
||||
* The formatting process operates as follows:
|
||||
*
|
||||
* * A new empty string `result` is created.
|
||||
* * If `urlObject.protocol` is a string, it is appended as-is to `result`.
|
||||
* * Otherwise, if `urlObject.protocol` is not `undefined` and is not a string, an `Error` is thrown.
|
||||
* * For all string values of `urlObject.protocol` that _do not end_ with an ASCII
|
||||
* colon (`:`) character, the literal string `:` will be appended to `result`.
|
||||
* * If either of the following conditions is true, then the literal string `//` will be appended to `result`:
|
||||
* * `urlObject.slashes` property is true;
|
||||
* * `urlObject.protocol` begins with `http`, `https`, `ftp`, `gopher`, or `file`;
|
||||
* * If the value of the `urlObject.auth` property is truthy, and either `urlObject.host` or `urlObject.hostname` are not `undefined`, the value of `urlObject.auth` will be coerced into a string
|
||||
* and appended to `result` followed by the literal string `@`.
|
||||
* * If the `urlObject.host` property is `undefined` then:
|
||||
* * If the `urlObject.hostname` is a string, it is appended to `result`.
|
||||
* * Otherwise, if `urlObject.hostname` is not `undefined` and is not a string,
|
||||
* an `Error` is thrown.
|
||||
* * If the `urlObject.port` property value is truthy, and `urlObject.hostname` is not `undefined`:
|
||||
* * The literal string `:` is appended to `result`, and
|
||||
* * The value of `urlObject.port` is coerced to a string and appended to `result`.
|
||||
* * Otherwise, if the `urlObject.host` property value is truthy, the value of `urlObject.host` is coerced to a string and appended to `result`.
|
||||
* * If the `urlObject.pathname` property is a string that is not an empty string:
|
||||
* * If the `urlObject.pathname` _does not start_ with an ASCII forward slash
|
||||
* (`/`), then the literal string `'/'` is appended to `result`.
|
||||
* * The value of `urlObject.pathname` is appended to `result`.
|
||||
* * Otherwise, if `urlObject.pathname` is not `undefined` and is not a string, an `Error` is thrown.
|
||||
* * If the `urlObject.search` property is `undefined` and if the `urlObject.query`property is an `Object`, the literal string `?` is appended to `result` followed by the output of calling the
|
||||
* `querystring` module's `stringify()` method passing the value of `urlObject.query`.
|
||||
* * Otherwise, if `urlObject.search` is a string:
|
||||
* * If the value of `urlObject.search` _does not start_ with the ASCII question
|
||||
* mark (`?`) character, the literal string `?` is appended to `result`.
|
||||
* * The value of `urlObject.search` is appended to `result`.
|
||||
* * Otherwise, if `urlObject.search` is not `undefined` and is not a string, an `Error` is thrown.
|
||||
* * If the `urlObject.hash` property is a string:
|
||||
* * If the value of `urlObject.hash` _does not start_ with the ASCII hash (`#`)
|
||||
* character, the literal string `#` is appended to `result`.
|
||||
* * The value of `urlObject.hash` is appended to `result`.
|
||||
* * Otherwise, if the `urlObject.hash` property is not `undefined` and is not a
|
||||
* string, an `Error` is thrown.
|
||||
* * `result` is returned.
|
||||
* @since v0.1.25
|
||||
* @legacy Use the WHATWG URL API instead.
|
||||
* @param urlObject A URL object (as returned by `url.parse()` or constructed otherwise). If a string, it is converted to an object by passing it to `url.parse()`.
|
||||
*/
|
||||
function format(urlObject: URL, options?: URLFormatOptions): string;
|
||||
/**
|
||||
* The `url.format()` method returns a formatted URL string derived from `urlObject`.
|
||||
*
|
||||
* ```js
|
||||
* import url from 'node:url';
|
||||
* url.format({
|
||||
* protocol: 'https',
|
||||
* hostname: 'example.com',
|
||||
* pathname: '/some/path',
|
||||
* query: {
|
||||
* page: 1,
|
||||
* format: 'json',
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* // => 'https://example.com/some/path?page=1&format=json'
|
||||
* ```
|
||||
*
|
||||
* If `urlObject` is not an object or a string, `url.format()` will throw a `TypeError`.
|
||||
*
|
||||
* The formatting process operates as follows:
|
||||
*
|
||||
* * A new empty string `result` is created.
|
||||
* * If `urlObject.protocol` is a string, it is appended as-is to `result`.
|
||||
* * Otherwise, if `urlObject.protocol` is not `undefined` and is not a string, an `Error` is thrown.
|
||||
* * For all string values of `urlObject.protocol` that _do not end_ with an ASCII
|
||||
* colon (`:`) character, the literal string `:` will be appended to `result`.
|
||||
* * If either of the following conditions is true, then the literal string `//` will be appended to `result`:
|
||||
* * `urlObject.slashes` property is true;
|
||||
* * `urlObject.protocol` begins with `http`, `https`, `ftp`, `gopher`, or `file`;
|
||||
* * If the value of the `urlObject.auth` property is truthy, and either `urlObject.host` or `urlObject.hostname` are not `undefined`, the value of `urlObject.auth` will be coerced into a string
|
||||
* and appended to `result` followed by the literal string `@`.
|
||||
* * If the `urlObject.host` property is `undefined` then:
|
||||
* * If the `urlObject.hostname` is a string, it is appended to `result`.
|
||||
* * Otherwise, if `urlObject.hostname` is not `undefined` and is not a string,
|
||||
* an `Error` is thrown.
|
||||
* * If the `urlObject.port` property value is truthy, and `urlObject.hostname` is not `undefined`:
|
||||
* * The literal string `:` is appended to `result`, and
|
||||
* * The value of `urlObject.port` is coerced to a string and appended to `result`.
|
||||
* * Otherwise, if the `urlObject.host` property value is truthy, the value of `urlObject.host` is coerced to a string and appended to `result`.
|
||||
* * If the `urlObject.pathname` property is a string that is not an empty string:
|
||||
* * If the `urlObject.pathname` _does not start_ with an ASCII forward slash
|
||||
* (`/`), then the literal string `'/'` is appended to `result`.
|
||||
* * The value of `urlObject.pathname` is appended to `result`.
|
||||
* * Otherwise, if `urlObject.pathname` is not `undefined` and is not a string, an `Error` is thrown.
|
||||
* * If the `urlObject.search` property is `undefined` and if the `urlObject.query`property is an `Object`, the literal string `?` is appended to `result` followed by the output of calling the
|
||||
* `querystring` module's `stringify()` method passing the value of `urlObject.query`.
|
||||
* * Otherwise, if `urlObject.search` is a string:
|
||||
* * If the value of `urlObject.search` _does not start_ with the ASCII question
|
||||
* mark (`?`) character, the literal string `?` is appended to `result`.
|
||||
* * The value of `urlObject.search` is appended to `result`.
|
||||
* * Otherwise, if `urlObject.search` is not `undefined` and is not a string, an `Error` is thrown.
|
||||
* * If the `urlObject.hash` property is a string:
|
||||
* * If the value of `urlObject.hash` _does not start_ with the ASCII hash (`#`)
|
||||
* character, the literal string `#` is appended to `result`.
|
||||
* * The value of `urlObject.hash` is appended to `result`.
|
||||
* * Otherwise, if the `urlObject.hash` property is not `undefined` and is not a
|
||||
* string, an `Error` is thrown.
|
||||
* * `result` is returned.
|
||||
* @since v0.1.25
|
||||
* @legacy Use the WHATWG URL API instead.
|
||||
* @param urlObject A URL object (as returned by `url.parse()` or constructed otherwise).
|
||||
*/
|
||||
function format(urlObject: UrlObject): string;
|
||||
/**
|
||||
* `url.format(urlString)` is shorthand for `url.format(url.parse(urlString))`.
|
||||
*
|
||||
* Because it invokes the deprecated `url.parse()` internally, passing a string argument
|
||||
* to `url.format()` is itself deprecated.
|
||||
*
|
||||
* Canonicalizing a URL string can be performed using the WHATWG URL API, by
|
||||
* constructing a new URL object and calling `url.toString()`.
|
||||
*
|
||||
* ```js
|
||||
* import { URL } from 'node:url';
|
||||
*
|
||||
* const unformatted = 'http://[fe80:0:0:0:0:0:0:1]:/a/b?a=b#abc';
|
||||
* const formatted = new URL(unformatted).toString();
|
||||
*
|
||||
* console.log(formatted); // Prints: http://[fe80::1]/a/b?a=b#abc
|
||||
* ```
|
||||
* @since v0.1.25
|
||||
* @deprecated Use the WHATWG URL API instead.
|
||||
* @param urlString A string that will be passed to `url.parse()` and then formatted.
|
||||
*/
|
||||
function format(urlString: string): string;
|
||||
/**
|
||||
* The `url.resolve()` method resolves a target URL relative to a base URL in a
|
||||
* manner similar to that of a web browser resolving an anchor tag.
|
||||
*
|
||||
* ```js
|
||||
* import url from 'node:url';
|
||||
* url.resolve('/one/two/three', 'four'); // '/one/two/four'
|
||||
* url.resolve('http://example.com/', '/one'); // 'http://example.com/one'
|
||||
* url.resolve('http://example.com/one', '/two'); // 'http://example.com/two'
|
||||
* ```
|
||||
*
|
||||
* Because it invokes the deprecated `url.parse()` internally, `url.resolve()` is itself deprecated.
|
||||
*
|
||||
* To achieve the same result using the WHATWG URL API:
|
||||
*
|
||||
* ```js
|
||||
* function resolve(from, to) {
|
||||
* const resolvedUrl = new URL(to, new URL(from, 'resolve://'));
|
||||
* if (resolvedUrl.protocol === 'resolve:') {
|
||||
* // `from` is a relative URL.
|
||||
* const { pathname, search, hash } = resolvedUrl;
|
||||
* return pathname + search + hash;
|
||||
* }
|
||||
* return resolvedUrl.toString();
|
||||
* }
|
||||
*
|
||||
* resolve('/one/two/three', 'four'); // '/one/two/four'
|
||||
* resolve('http://example.com/', '/one'); // 'http://example.com/one'
|
||||
* resolve('http://example.com/one', '/two'); // 'http://example.com/two'
|
||||
* ```
|
||||
* @since v0.1.25
|
||||
* @deprecated Use the WHATWG URL API instead.
|
||||
* @param from The base URL to use if `to` is a relative URL.
|
||||
* @param to The target URL to resolve.
|
||||
*/
|
||||
function resolve(from: string, to: string): string;
|
||||
/**
|
||||
* Returns the [Punycode](https://tools.ietf.org/html/rfc5891#section-4.4) ASCII serialization of the `domain`. If `domain` is an
|
||||
* invalid domain, the empty string is returned.
|
||||
*
|
||||
* It performs the inverse operation to {@link domainToUnicode}.
|
||||
*
|
||||
* ```js
|
||||
* import url from 'node:url';
|
||||
*
|
||||
* console.log(url.domainToASCII('español.com'));
|
||||
* // Prints xn--espaol-zwa.com
|
||||
* console.log(url.domainToASCII('中文.com'));
|
||||
* // Prints xn--fiq228c.com
|
||||
* console.log(url.domainToASCII('xn--iñvalid.com'));
|
||||
* // Prints an empty string
|
||||
* ```
|
||||
* @since v7.4.0, v6.13.0
|
||||
*/
|
||||
function domainToASCII(domain: string): string;
|
||||
/**
|
||||
* Returns the Unicode serialization of the `domain`. If `domain` is an invalid
|
||||
* domain, the empty string is returned.
|
||||
*
|
||||
* It performs the inverse operation to {@link domainToASCII}.
|
||||
*
|
||||
* ```js
|
||||
* import url from 'node:url';
|
||||
*
|
||||
* console.log(url.domainToUnicode('xn--espaol-zwa.com'));
|
||||
* // Prints español.com
|
||||
* console.log(url.domainToUnicode('xn--fiq228c.com'));
|
||||
* // Prints 中文.com
|
||||
* console.log(url.domainToUnicode('xn--iñvalid.com'));
|
||||
* // Prints an empty string
|
||||
* ```
|
||||
* @since v7.4.0, v6.13.0
|
||||
*/
|
||||
function domainToUnicode(domain: string): string;
|
||||
/**
|
||||
* This function ensures the correct decodings of percent-encoded characters as
|
||||
* well as ensuring a cross-platform valid absolute path string.
|
||||
*
|
||||
* ```js
|
||||
* import { fileURLToPath } from 'node:url';
|
||||
*
|
||||
* const __filename = fileURLToPath(import.meta.url);
|
||||
*
|
||||
* new URL('file:///C:/path/').pathname; // Incorrect: /C:/path/
|
||||
* fileURLToPath('file:///C:/path/'); // Correct: C:\path\ (Windows)
|
||||
*
|
||||
* new URL('file://nas/foo.txt').pathname; // Incorrect: /foo.txt
|
||||
* fileURLToPath('file://nas/foo.txt'); // Correct: \\nas\foo.txt (Windows)
|
||||
*
|
||||
* new URL('file:///你好.txt').pathname; // Incorrect: /%E4%BD%A0%E5%A5%BD.txt
|
||||
* fileURLToPath('file:///你好.txt'); // Correct: /你好.txt (POSIX)
|
||||
*
|
||||
* new URL('file:///hello world').pathname; // Incorrect: /hello%20world
|
||||
* fileURLToPath('file:///hello world'); // Correct: /hello world (POSIX)
|
||||
* ```
|
||||
*
|
||||
* **Security Considerations:**
|
||||
*
|
||||
* This function decodes percent-encoded characters, including encoded dot-segments
|
||||
* (`%2e` as `.` and `%2e%2e` as `..`), and then normalizes the resulting path.
|
||||
* This means that encoded directory traversal sequences (such as `%2e%2e`) are
|
||||
* decoded and processed as actual path traversal, even though encoded slashes
|
||||
* (`%2F`, `%5C`) are correctly rejected.
|
||||
*
|
||||
* **Applications must not rely on `fileURLToPath()` alone to prevent directory
|
||||
* traversal attacks.** Always perform explicit path validation and security checks
|
||||
* on the returned path value to ensure it remains within expected boundaries
|
||||
* before using it for file system operations.
|
||||
* @since v10.12.0
|
||||
* @param url The file URL string or URL object to convert to a path.
|
||||
* @return The fully-resolved platform-specific Node.js file path.
|
||||
*/
|
||||
function fileURLToPath(url: string | URL, options?: FileUrlToPathOptions): string;
|
||||
/**
|
||||
* Like `url.fileURLToPath(...)` except that instead of returning a string
|
||||
* representation of the path, a `Buffer` is returned. This conversion is
|
||||
* helpful when the input URL contains percent-encoded segments that are
|
||||
* not valid UTF-8 / Unicode sequences.
|
||||
*
|
||||
* **Security Considerations:**
|
||||
*
|
||||
* This function has the same security considerations as `url.fileURLToPath()`.
|
||||
* It decodes percent-encoded characters, including encoded dot-segments
|
||||
* (`%2e` as `.` and `%2e%2e` as `..`), and normalizes the path. **Applications
|
||||
* must not rely on this function alone to prevent directory traversal attacks.**
|
||||
* Always perform explicit path validation on the returned buffer value before
|
||||
* using it for file system operations.
|
||||
* @since v24.3.0
|
||||
* @param url The file URL string or URL object to convert to a path.
|
||||
* @returns The fully-resolved platform-specific Node.js file path
|
||||
* as a `Buffer`.
|
||||
*/
|
||||
function fileURLToPathBuffer(url: string | URL, options?: FileUrlToPathOptions): NonSharedBuffer;
|
||||
/**
|
||||
* This function ensures that `path` is resolved absolutely, and that the URL
|
||||
* control characters are correctly encoded when converting into a File URL.
|
||||
*
|
||||
* ```js
|
||||
* import { pathToFileURL } from 'node:url';
|
||||
*
|
||||
* new URL('/foo#1', 'file:'); // Incorrect: file:///foo#1
|
||||
* pathToFileURL('/foo#1'); // Correct: file:///foo%231 (POSIX)
|
||||
*
|
||||
* new URL('/some/path%.c', 'file:'); // Incorrect: file:///some/path%.c
|
||||
* pathToFileURL('/some/path%.c'); // Correct: file:///some/path%25.c (POSIX)
|
||||
* ```
|
||||
* @since v10.12.0
|
||||
* @param path The path to convert to a File URL.
|
||||
* @return The file URL object.
|
||||
*/
|
||||
function pathToFileURL(path: string, options?: PathToFileUrlOptions): URL;
|
||||
/**
|
||||
* This utility function converts a URL object into an ordinary options object as
|
||||
* expected by the `http.request()` and `https.request()` APIs.
|
||||
*
|
||||
* ```js
|
||||
* import { urlToHttpOptions } from 'node:url';
|
||||
* const myURL = new URL('https://a:b@測試?abc#foo');
|
||||
*
|
||||
* console.log(urlToHttpOptions(myURL));
|
||||
* /*
|
||||
* {
|
||||
* protocol: 'https:',
|
||||
* hostname: 'xn--g6w251d',
|
||||
* hash: '#foo',
|
||||
* search: '?abc',
|
||||
* pathname: '/',
|
||||
* path: '/?abc',
|
||||
* href: 'https://a:b@xn--g6w251d/?abc#foo',
|
||||
* auth: 'a:b'
|
||||
* }
|
||||
*
|
||||
* ```
|
||||
* @since v15.7.0, v14.18.0
|
||||
* @param url The `WHATWG URL` object to convert to an options object.
|
||||
* @return Options object
|
||||
*/
|
||||
function urlToHttpOptions(url: URL): ClientRequestArgs;
|
||||
interface URLFormatOptions {
|
||||
/**
|
||||
* `true` if the serialized URL string should include the username and password, `false` otherwise.
|
||||
* @default true
|
||||
*/
|
||||
auth?: boolean | undefined;
|
||||
/**
|
||||
* `true` if the serialized URL string should include the fragment, `false` otherwise.
|
||||
* @default true
|
||||
*/
|
||||
fragment?: boolean | undefined;
|
||||
/**
|
||||
* `true` if the serialized URL string should include the search query, `false` otherwise.
|
||||
* @default true
|
||||
*/
|
||||
search?: boolean | undefined;
|
||||
/**
|
||||
* `true` if Unicode characters appearing in the host component of the URL string should be encoded directly as opposed to
|
||||
* being Punycode encoded.
|
||||
* @default false
|
||||
*/
|
||||
unicode?: boolean | undefined;
|
||||
}
|
||||
// #region web types
|
||||
type URLPatternInput = string | URLPatternInit;
|
||||
interface URLPatternComponentResult {
|
||||
input: string;
|
||||
groups: Record<string, string | undefined>;
|
||||
}
|
||||
interface URLPatternInit {
|
||||
protocol?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
hostname?: string;
|
||||
port?: string;
|
||||
pathname?: string;
|
||||
search?: string;
|
||||
hash?: string;
|
||||
baseURL?: string;
|
||||
}
|
||||
interface URLPatternOptions {
|
||||
ignoreCase?: boolean;
|
||||
}
|
||||
interface URLPatternResult {
|
||||
inputs: URLPatternInput[];
|
||||
protocol: URLPatternComponentResult;
|
||||
username: URLPatternComponentResult;
|
||||
password: URLPatternComponentResult;
|
||||
hostname: URLPatternComponentResult;
|
||||
port: URLPatternComponentResult;
|
||||
pathname: URLPatternComponentResult;
|
||||
search: URLPatternComponentResult;
|
||||
hash: URLPatternComponentResult;
|
||||
}
|
||||
interface URL {
|
||||
hash: string;
|
||||
host: string;
|
||||
hostname: string;
|
||||
href: string;
|
||||
readonly origin: string;
|
||||
password: string;
|
||||
pathname: string;
|
||||
port: string;
|
||||
protocol: string;
|
||||
search: string;
|
||||
readonly searchParams: URLSearchParams;
|
||||
username: string;
|
||||
toJSON(): string;
|
||||
}
|
||||
var URL: {
|
||||
prototype: URL;
|
||||
new(url: string | URL, base?: string | URL): URL;
|
||||
canParse(input: string | URL, base?: string | URL): boolean;
|
||||
createObjectURL(blob: Blob): string;
|
||||
parse(input: string | URL, base?: string | URL): URL | null;
|
||||
revokeObjectURL(id: string): void;
|
||||
};
|
||||
interface URLPattern {
|
||||
readonly hasRegExpGroups: boolean;
|
||||
readonly hash: string;
|
||||
readonly hostname: string;
|
||||
readonly password: string;
|
||||
readonly pathname: string;
|
||||
readonly port: string;
|
||||
readonly protocol: string;
|
||||
readonly search: string;
|
||||
readonly username: string;
|
||||
exec(input?: URLPatternInput, baseURL?: string | URL): URLPatternResult | null;
|
||||
test(input?: URLPatternInput, baseURL?: string | URL): boolean;
|
||||
}
|
||||
var URLPattern: {
|
||||
prototype: URLPattern;
|
||||
new(input: URLPatternInput, baseURL: string | URL, options?: URLPatternOptions): URLPattern;
|
||||
new(input?: URLPatternInput, options?: URLPatternOptions): URLPattern;
|
||||
};
|
||||
interface URLSearchParams {
|
||||
readonly size: number;
|
||||
append(name: string, value: string): void;
|
||||
delete(name: string, value?: string): void;
|
||||
get(name: string): string | null;
|
||||
getAll(name: string): string[];
|
||||
has(name: string, value?: string): boolean;
|
||||
set(name: string, value: string): void;
|
||||
sort(): void;
|
||||
forEach(callbackfn: (value: string, key: string, parent: URLSearchParams) => void, thisArg?: any): void;
|
||||
[Symbol.iterator](): URLSearchParamsIterator<[string, string]>;
|
||||
entries(): URLSearchParamsIterator<[string, string]>;
|
||||
keys(): URLSearchParamsIterator<string>;
|
||||
values(): URLSearchParamsIterator<string>;
|
||||
}
|
||||
var URLSearchParams: {
|
||||
prototype: URLSearchParams;
|
||||
new(init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams;
|
||||
};
|
||||
interface URLSearchParamsIterator<T> extends NodeJS.Iterator<T, BuiltinIteratorReturn, unknown> {
|
||||
[Symbol.iterator](): URLSearchParamsIterator<T>;
|
||||
}
|
||||
// #endregion
|
||||
}
|
||||
declare module "url" {
|
||||
export * from "node:url";
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"syncChannel.d.ts","sourceRoot":"","sources":["../../src/api/syncChannel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA8EH;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,SAAS,CAAgE;IAEjF,OAAO,CAAC,cAAc,CAA6B;IAMnD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IAKxC,aAAa,SAAK;IAClB,iBAAiB,SAAK;IAEtB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,WAAW,CAAqB;IAExC,OAAO,CAAC,SAAS,CAAyB;IAG1C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,UAAU,CAAK;IAGvB,OAAO,CAAC,QAAQ,CAA6B;gBAEjC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,aAAa,UAAQ;IAmF9D;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAMpD;;;OAGG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU;IAKlE,mEAAmE;IACnE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI;IAIzF,oDAAoD;IACpD,KAAK,IAAI,IAAI;IAsBb,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,gBAAgB;IA8CxB;;;;;;;OAOG;IACH,OAAO,CAAC,UAAU;IAiClB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IA0DlB;;;;OAIG;IACH,OAAO,CAAC,SAAS;IA2BjB;;OAEG;IACH,OAAO,CAAC,OAAO;IA0Bf,yEAAyE;IACzE,OAAO,CAAC,QAAQ;IAOhB,uDAAuD;IACvD,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,SAAS;IAiBjB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAsBtB;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAoCrB;;;OAGG;IACH,OAAO,CAAC,WAAW;CAiBtB"}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { TSESTree } from '@typescript-eslint/types';
|
||||
import type { Reference } from '../referencer/Reference';
|
||||
import type { ScopeManager } from '../ScopeManager';
|
||||
import type { Variable } from '../variable';
|
||||
import type { Scope } from './Scope';
|
||||
import { ScopeBase } from './ScopeBase';
|
||||
import { ScopeType } from './ScopeType';
|
||||
export declare class FunctionScope extends ScopeBase<ScopeType.function, TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.Program | TSESTree.TSDeclareFunction | TSESTree.TSEmptyBodyFunctionExpression, Scope> {
|
||||
constructor(scopeManager: ScopeManager, upperScope: FunctionScope['upper'], block: FunctionScope['block'], isMethodDefinition: boolean);
|
||||
protected isValidResolution(ref: Reference, variable: Variable): boolean;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"u32.d.ts","sourceRoot":"","sources":["../../src/u32.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvG,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,GAAI,SAAQ,iBAAsB,KAAG,gBAAgB,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,CAO5F,CAAC;AAEP;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,GAAI,SAAQ,iBAAsB,KAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAMnF,CAAC;AAEP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,WAAW,GAAI,SAAQ,iBAAsB,KAAG,cAAc,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,CACxC,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
import * as z from "./v4/classic/external.cjs";
|
||||
export * from "./v4/classic/external.cjs";
|
||||
export { z };
|
||||
export default z;
|
||||
@@ -0,0 +1,34 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const { createWarning } = require('..')
|
||||
const { withResolvers } = require('./promise')
|
||||
|
||||
test('emit with interpolated string', t => {
|
||||
t.plan(4)
|
||||
|
||||
const { promise, resolve } = withResolvers()
|
||||
|
||||
process.on('warning', onWarning)
|
||||
function onWarning (warning) {
|
||||
t.assert.deepStrictEqual(warning.name, 'TestDeprecation')
|
||||
t.assert.deepStrictEqual(warning.code, 'CODE')
|
||||
t.assert.deepStrictEqual(warning.message, 'Hello world')
|
||||
t.assert.ok(codeWarning.emitted)
|
||||
}
|
||||
|
||||
const codeWarning = createWarning({
|
||||
name: 'TestDeprecation',
|
||||
code: 'CODE',
|
||||
message: 'Hello %s'
|
||||
})
|
||||
codeWarning('world')
|
||||
codeWarning('world')
|
||||
|
||||
setImmediate(() => {
|
||||
process.removeListener('warning', onWarning)
|
||||
resolve()
|
||||
})
|
||||
|
||||
return promise
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
const { Linter } = require("./linter");
|
||||
const SourceCodeFixer = require("./source-code-fixer");
|
||||
|
||||
module.exports = {
|
||||
Linter,
|
||||
|
||||
// For testers.
|
||||
SourceCodeFixer,
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,191 @@
|
||||
<p align="center">
|
||||
<img src="logo.svg" width="200px" align="center" alt="Zod logo" />
|
||||
<h1 align="center">Zod</h1>
|
||||
<p align="center">
|
||||
TypeScript-first schema validation with static type inference
|
||||
<br/>
|
||||
by <a href="https://x.com/colinhacks">@colinhacks</a>
|
||||
</p>
|
||||
</p>
|
||||
<br/>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/colinhacks/zod/actions?query=branch%3Amain"><img src="https://github.com/colinhacks/zod/actions/workflows/test.yml/badge.svg?event=push&branch=main" alt="Zod CI status" /></a>
|
||||
<a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/colinhacks/zod" alt="License"></a>
|
||||
<a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/npm/dw/zod.svg" alt="npm"></a>
|
||||
<a href="https://discord.gg/KaSRdyX2vc" rel="nofollow"><img src="https://img.shields.io/discord/893487829802418277?label=Discord&logo=discord&logoColor=white" alt="discord server"></a>
|
||||
<a href="https://github.com/colinhacks/zod" rel="nofollow"><img src="https://img.shields.io/github/stars/colinhacks/zod" alt="stars"></a>
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
<a href="https://zod.dev/api">Docs</a>
|
||||
<span> • </span>
|
||||
<a href="https://discord.gg/RcG33DQJdf">Discord</a>
|
||||
<span> • </span>
|
||||
<a href="https://twitter.com/colinhacks">𝕏</a>
|
||||
<span> • </span>
|
||||
<a href="https://bsky.app/profile/zod.dev">Bluesky</a>
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
### [Read the docs →](https://zod.dev/api)
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
## What is Zod?
|
||||
|
||||
Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result.
|
||||
|
||||
```ts
|
||||
import * as z from "zod";
|
||||
|
||||
const User = z.object({
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
// some untrusted data...
|
||||
const input = {
|
||||
/* stuff */
|
||||
};
|
||||
|
||||
// the parsed result is validated and type safe!
|
||||
const data = User.parse(input);
|
||||
|
||||
// so you can use it with confidence :)
|
||||
console.log(data.name);
|
||||
```
|
||||
|
||||
<br/>
|
||||
|
||||
## Features
|
||||
|
||||
- Zero external dependencies
|
||||
- Works in Node.js and all modern browsers
|
||||
- Tiny: `2kb` core bundle (gzipped)
|
||||
- Immutable API: methods return a new instance
|
||||
- Concise interface
|
||||
- Works with TypeScript and plain JS
|
||||
- Built-in JSON Schema conversion
|
||||
- Extensive ecosystem
|
||||
|
||||
<br/>
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install zod
|
||||
```
|
||||
|
||||
<br/>
|
||||
|
||||
## Basic usage
|
||||
|
||||
Before you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema.
|
||||
|
||||
```ts
|
||||
import * as z from "zod";
|
||||
|
||||
const Player = z.object({
|
||||
username: z.string(),
|
||||
xp: z.number(),
|
||||
});
|
||||
```
|
||||
|
||||
### Parsing data
|
||||
|
||||
Given any Zod schema, use `.parse` to validate an input. If it's valid, Zod returns a strongly-typed _deep clone_ of the input.
|
||||
|
||||
```ts
|
||||
Player.parse({ username: "billie", xp: 100 });
|
||||
// => returns { username: "billie", xp: 100 }
|
||||
```
|
||||
|
||||
**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](https://zod.dev/api#refinements) or [transforms](https://zod.dev/api#transforms), you'll need to use the `.parseAsync()` method instead.
|
||||
|
||||
```ts
|
||||
const schema = z.string().refine(async (val) => val.length <= 8);
|
||||
|
||||
await schema.parseAsync("hello");
|
||||
// => "hello"
|
||||
```
|
||||
|
||||
### Handling errors
|
||||
|
||||
When validation fails, the `.parse()` method will throw a `ZodError` instance with granular information about the validation issues.
|
||||
|
||||
```ts
|
||||
try {
|
||||
Player.parse({ username: 42, xp: "100" });
|
||||
} catch (err) {
|
||||
if (err instanceof z.ZodError) {
|
||||
err.issues;
|
||||
/* [
|
||||
{
|
||||
expected: 'string',
|
||||
code: 'invalid_type',
|
||||
path: [ 'username' ],
|
||||
message: 'Invalid input: expected string'
|
||||
},
|
||||
{
|
||||
expected: 'number',
|
||||
code: 'invalid_type',
|
||||
path: [ 'xp' ],
|
||||
message: 'Invalid input: expected number'
|
||||
}
|
||||
] */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To avoid a `try/catch` block, you can use the `.safeParse()` method to get back a plain result object containing either the successfully parsed data or a `ZodError`. The result type is a [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions), so you can handle both cases conveniently.
|
||||
|
||||
```ts
|
||||
const result = Player.safeParse({ username: 42, xp: "100" });
|
||||
if (!result.success) {
|
||||
result.error; // ZodError instance
|
||||
} else {
|
||||
result.data; // { username: string; xp: number }
|
||||
}
|
||||
```
|
||||
|
||||
**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](https://zod.dev/api#refinements) or [transforms](https://zod.dev/api#transforms), you'll need to use the `.safeParseAsync()` method instead.
|
||||
|
||||
```ts
|
||||
const schema = z.string().refine(async (val) => val.length <= 8);
|
||||
|
||||
await schema.safeParseAsync("hello");
|
||||
// => { success: true; data: "hello" }
|
||||
```
|
||||
|
||||
### Inferring types
|
||||
|
||||
Zod infers a static type from your schema definitions. You can extract this type with the `z.infer<>` utility and use it however you like.
|
||||
|
||||
```ts
|
||||
const Player = z.object({
|
||||
username: z.string(),
|
||||
xp: z.number(),
|
||||
});
|
||||
|
||||
// extract the inferred type
|
||||
type Player = z.infer<typeof Player>;
|
||||
|
||||
// use it in your code
|
||||
const player: Player = { username: "billie", xp: 100 };
|
||||
```
|
||||
|
||||
In some cases, the input & output types of a schema can diverge. For instance, the `.transform()` API can convert the input from one type to another. In these cases, you can extract the input and output types independently:
|
||||
|
||||
```ts
|
||||
const mySchema = z.string().transform((val) => val.length);
|
||||
|
||||
type MySchemaIn = z.input<typeof mySchema>;
|
||||
// => string
|
||||
|
||||
type MySchemaOut = z.output<typeof mySchema>; // equivalent to z.infer<typeof mySchema>
|
||||
// number
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const index = require('./index.js')
|
||||
const { readdirSync } = require('node:fs')
|
||||
const { basename } = require('node:path')
|
||||
|
||||
test(
|
||||
'index exports exactly all non-test files excluding itself',
|
||||
t => {
|
||||
// Read all files in the `util` directory
|
||||
const files = readdirSync(__dirname)
|
||||
|
||||
for (const file of files) {
|
||||
const kebabName = basename(file, '.js')
|
||||
const snakeName = kebabName.split('-').map((part, idx) => {
|
||||
if (idx === 0) return part
|
||||
return part[0].toUpperCase() + part.slice(1)
|
||||
}).join('')
|
||||
|
||||
if (file.endsWith('.test.js') === false && file !== 'index.js') {
|
||||
// We expect all files to be exported except…
|
||||
t.assert.ok(index[snakeName], `exports ${snakeName}`)
|
||||
} else {
|
||||
// …test files and the index file itself – those must not be exported
|
||||
t.assert.ok(!index[snakeName], `does not export ${snakeName}`)
|
||||
}
|
||||
|
||||
// Remove the exported file from the index object
|
||||
delete index[snakeName]
|
||||
}
|
||||
|
||||
// Now the index is expected to be empty, as nothing else should be
|
||||
// exported from it
|
||||
t.assert.deepStrictEqual(index, {}, 'does not export anything else')
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user