WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
var test = require('tape');
|
||||
var stringify = require('../');
|
||||
|
||||
test('simple object', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { c: 6, b: [4,5], a: 3, z: null };
|
||||
t.equal(stringify(obj), '{"a":3,"b":[4,5],"c":6,"z":null}');
|
||||
});
|
||||
|
||||
test('object with undefined', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { a: 3, z: undefined };
|
||||
t.equal(stringify(obj), '{"a":3}');
|
||||
});
|
||||
|
||||
test('object with null', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { a: 3, z: null };
|
||||
t.equal(stringify(obj), '{"a":3,"z":null}');
|
||||
});
|
||||
|
||||
test('object with NaN and Infinity', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { a: 3, b: NaN, c: Infinity };
|
||||
t.equal(stringify(obj), '{"a":3,"b":null,"c":null}');
|
||||
});
|
||||
|
||||
test('array with undefined', function (t) {
|
||||
t.plan(1);
|
||||
var obj = [4, undefined, 6];
|
||||
t.equal(stringify(obj), '[4,null,6]');
|
||||
});
|
||||
|
||||
test('object with empty string', function (t) {
|
||||
t.plan(1);
|
||||
var obj = { a: 3, z: '' };
|
||||
t.equal(stringify(obj), '{"a":3,"z":""}');
|
||||
});
|
||||
|
||||
test('array with empty string', function (t) {
|
||||
t.plan(1);
|
||||
var obj = [4, '', 6];
|
||||
t.equal(stringify(obj), '[4,"",6]');
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
var assert = require("assert");
|
||||
var indexStringify = require('../index');
|
||||
var jsonStableStringify = require('json-stable-stringify');
|
||||
|
||||
var validateLibOutput = require('./validate');
|
||||
|
||||
var data = require("../fixtures/index").input;
|
||||
var dataLength = JSON.stringify(data).length;
|
||||
|
||||
suite("libs", function() {
|
||||
|
||||
var minSamples = 120;
|
||||
|
||||
// This needs to be true before anything else
|
||||
console.log('Checking index validity...');
|
||||
validateLibOutput(indexStringify);
|
||||
console.log('Checking index validity success');
|
||||
|
||||
benchmark('index', function () {
|
||||
var result = indexStringify(data);
|
||||
assert.equal(result.length, dataLength);
|
||||
}, {
|
||||
minSamples: minSamples
|
||||
});
|
||||
|
||||
benchmark('json-stable-stringify', function () {
|
||||
var result = jsonStableStringify(data);
|
||||
assert.equal(result.length, dataLength);
|
||||
}, {
|
||||
minSamples: minSamples
|
||||
});
|
||||
|
||||
}, {
|
||||
onComplete: function() {
|
||||
var namesFastest = this
|
||||
.filter(function(bench) {
|
||||
return bench.name !== 'native';
|
||||
})
|
||||
.filter('fastest')
|
||||
.map('name');
|
||||
assert.notEqual(namesFastest.indexOf('index'), -1, "index should be among the fastest");
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
"use strict";var c=Object.defineProperty;var a=(r,t)=>c(r,"name",{value:t,configurable:!0});var s=require("./get-pipe-path-D4YM6rQt.cjs"),n=require("./register-C557imBs.cjs");let e;const i=a((r,t)=>(e||(e=n.register({namespace:Date.now().toString()})),e.require(r,t)),"tsxRequire"),o=a((r,t,u)=>(e||(e=n.register({namespace:Date.now().toString()})),e.resolve(r,t,u)),"resolve");o.paths=s.require.resolve.paths,i.resolve=o,i.main=s.require.main,i.extensions=s.require.extensions,i.cache=s.require.cache,exports.tsxRequire=i;
|
||||
@@ -0,0 +1,261 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const fs = require('fs')
|
||||
const proxyquire = require('proxyquire')
|
||||
const SonicBoom = require('../')
|
||||
const { file } = require('./helper')
|
||||
|
||||
test('write buffers that are not totally written with sync mode', (t) => {
|
||||
t.plan(9)
|
||||
|
||||
const fakeFs = Object.create(fs)
|
||||
fakeFs.writeSync = function (fd, buf, enc) {
|
||||
t.pass('fake fs.write called')
|
||||
fakeFs.writeSync = (fd, buf, enc) => {
|
||||
t.pass('calling real fs.writeSync, ' + buf)
|
||||
return fs.writeSync(fd, buf, enc)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
const SonicBoom = proxyquire('../', {
|
||||
fs: fakeFs
|
||||
})
|
||||
|
||||
const dest = file()
|
||||
const fd = fs.openSync(dest, 'w')
|
||||
const stream = new SonicBoom({ fd, minLength: 0, sync: true })
|
||||
|
||||
stream.on('ready', () => {
|
||||
t.pass('ready emitted')
|
||||
})
|
||||
|
||||
t.ok(stream.write('hello world\n'))
|
||||
t.ok(stream.write('something else\n'))
|
||||
|
||||
stream.end()
|
||||
|
||||
stream.on('finish', () => {
|
||||
fs.readFile(dest, 'utf8', (err, data) => {
|
||||
t.error(err)
|
||||
t.equal(data, 'hello world\nsomething else\n')
|
||||
})
|
||||
})
|
||||
stream.on('close', () => {
|
||||
t.pass('close emitted')
|
||||
})
|
||||
})
|
||||
|
||||
test('write buffers that are not totally written with flush sync', (t) => {
|
||||
t.plan(7)
|
||||
|
||||
const fakeFs = Object.create(fs)
|
||||
fakeFs.writeSync = function (fd, buf, enc) {
|
||||
t.pass('fake fs.write called')
|
||||
fakeFs.writeSync = fs.writeSync
|
||||
return 0
|
||||
}
|
||||
const SonicBoom = proxyquire('../', {
|
||||
fs: fakeFs
|
||||
})
|
||||
|
||||
const dest = file()
|
||||
const fd = fs.openSync(dest, 'w')
|
||||
const stream = new SonicBoom({ fd, minLength: 100, sync: false })
|
||||
|
||||
stream.on('ready', () => {
|
||||
t.pass('ready emitted')
|
||||
})
|
||||
|
||||
t.ok(stream.write('hello world\n'))
|
||||
t.ok(stream.write('something else\n'))
|
||||
|
||||
stream.flushSync()
|
||||
|
||||
stream.on('write', (n) => {
|
||||
if (n === 0) {
|
||||
t.fail('throwing to avoid infinite loop')
|
||||
throw Error('shouldn\'t call write handler after flushing with n === 0')
|
||||
}
|
||||
})
|
||||
|
||||
stream.end()
|
||||
|
||||
stream.on('finish', () => {
|
||||
fs.readFile(dest, 'utf8', (err, data) => {
|
||||
t.error(err)
|
||||
t.equal(data, 'hello world\nsomething else\n')
|
||||
})
|
||||
})
|
||||
stream.on('close', () => {
|
||||
t.pass('close emitted')
|
||||
})
|
||||
})
|
||||
|
||||
test('sync writing is fully sync', (t) => {
|
||||
t.plan(6)
|
||||
|
||||
const fakeFs = Object.create(fs)
|
||||
fakeFs.writeSync = function (fd, buf, enc, cb) {
|
||||
t.pass('fake fs.write called')
|
||||
return fs.writeSync(fd, buf, enc)
|
||||
}
|
||||
const SonicBoom = proxyquire('../', {
|
||||
fs: fakeFs
|
||||
})
|
||||
|
||||
const dest = file()
|
||||
const fd = fs.openSync(dest, 'w')
|
||||
const stream = new SonicBoom({ fd, minLength: 0, sync: true })
|
||||
t.ok(stream.write('hello world\n'))
|
||||
t.ok(stream.write('something else\n'))
|
||||
|
||||
// 'drain' will be only emitted once,
|
||||
// the number of assertions at the top check this.
|
||||
stream.on('drain', () => {
|
||||
t.pass('drain emitted')
|
||||
})
|
||||
|
||||
const data = fs.readFileSync(dest, 'utf8')
|
||||
t.equal(data, 'hello world\nsomething else\n')
|
||||
})
|
||||
|
||||
test('write enormously large buffers sync', (t) => {
|
||||
t.plan(3)
|
||||
|
||||
const dest = file()
|
||||
const fd = fs.openSync(dest, 'w')
|
||||
const stream = new SonicBoom({ fd, minLength: 0, sync: true })
|
||||
|
||||
const buf = Buffer.alloc(1024).fill('x').toString() // 1 MB
|
||||
let length = 0
|
||||
|
||||
for (let i = 0; i < 1024 * 512; i++) {
|
||||
length += buf.length
|
||||
stream.write(buf)
|
||||
}
|
||||
|
||||
stream.end()
|
||||
|
||||
stream.on('finish', () => {
|
||||
fs.stat(dest, (err, stat) => {
|
||||
t.error(err)
|
||||
t.equal(stat.size, length)
|
||||
})
|
||||
})
|
||||
stream.on('close', () => {
|
||||
t.pass('close emitted')
|
||||
})
|
||||
})
|
||||
|
||||
test('write enormously large buffers sync with utf8 multi-byte split', (t) => {
|
||||
t.plan(4)
|
||||
|
||||
const dest = file()
|
||||
const fd = fs.openSync(dest, 'w')
|
||||
const stream = new SonicBoom({ fd, minLength: 0, sync: true })
|
||||
|
||||
let buf = Buffer.alloc((1024 * 16) - 2).fill('x') // 16MB - 3B
|
||||
const length = buf.length + 4
|
||||
buf = buf.toString() + '🌲' // 16 MB + 1B
|
||||
|
||||
stream.write(buf)
|
||||
|
||||
stream.end()
|
||||
|
||||
stream.on('finish', () => {
|
||||
fs.stat(dest, (err, stat) => {
|
||||
t.error(err)
|
||||
t.equal(stat.size, length)
|
||||
const char = Buffer.alloc(4)
|
||||
const fd = fs.openSync(dest, 'r')
|
||||
fs.readSync(fd, char, 0, 4, length - 4)
|
||||
t.equal(char.toString(), '🌲')
|
||||
})
|
||||
})
|
||||
stream.on('close', () => {
|
||||
t.pass('close emitted')
|
||||
})
|
||||
})
|
||||
|
||||
// for context see this issue https://github.com/pinojs/pino/issues/871
|
||||
test('file specified by dest path available immediately when options.sync is true', (t) => {
|
||||
t.plan(3)
|
||||
const dest = file()
|
||||
const stream = new SonicBoom({ dest, sync: true })
|
||||
t.ok(stream.write('hello world\n'))
|
||||
t.ok(stream.write('something else\n'))
|
||||
stream.flushSync()
|
||||
t.pass('file opened and written to without error')
|
||||
})
|
||||
|
||||
test('sync error handling', (t) => {
|
||||
t.plan(1)
|
||||
try {
|
||||
/* eslint no-new: off */
|
||||
new SonicBoom({ dest: '/path/to/nowwhere', sync: true })
|
||||
t.fail('must throw synchronously')
|
||||
} catch (err) {
|
||||
t.pass('an error happened')
|
||||
}
|
||||
})
|
||||
|
||||
for (const fd of [1, 2]) {
|
||||
test(`fd ${fd}`, (t) => {
|
||||
t.plan(1)
|
||||
|
||||
const fakeFs = Object.create(fs)
|
||||
const SonicBoom = proxyquire('../', {
|
||||
fs: fakeFs
|
||||
})
|
||||
|
||||
const stream = new SonicBoom({ fd })
|
||||
|
||||
fakeFs.close = function (fd, cb) {
|
||||
t.fail(`should not close fd ${fd}`)
|
||||
}
|
||||
|
||||
stream.end()
|
||||
|
||||
stream.on('close', () => {
|
||||
t.pass('close emitted')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
test('._len must always be equal or greater than 0', (t) => {
|
||||
t.plan(3)
|
||||
|
||||
const dest = file()
|
||||
const fd = fs.openSync(dest, 'w')
|
||||
const stream = new SonicBoom({ fd, sync: true })
|
||||
|
||||
t.ok(stream.write('hello world 👀\n'))
|
||||
t.ok(stream.write('another line 👀\n'))
|
||||
|
||||
t.equal(stream._len, 0)
|
||||
|
||||
stream.end()
|
||||
})
|
||||
|
||||
test('._len must always be equal or greater than 0', (t) => {
|
||||
const n = 20
|
||||
t.plan(n + 3)
|
||||
|
||||
const dest = file()
|
||||
const fd = fs.openSync(dest, 'w')
|
||||
const stream = new SonicBoom({ fd, sync: true, minLength: 20 })
|
||||
|
||||
let str = ''
|
||||
for (let i = 0; i < 20; i++) {
|
||||
t.ok(stream.write('👀'))
|
||||
str += '👀'
|
||||
}
|
||||
|
||||
t.equal(stream._len, 0)
|
||||
|
||||
fs.readFile(dest, 'utf8', (err, data) => {
|
||||
t.error(err)
|
||||
t.equal(data, str)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert'
|
||||
import { hostname } from 'node:os'
|
||||
import { readFileSync } from 'node:fs'
|
||||
|
||||
import { sink, check, once, watchFileCreated, file } from '../helper.js'
|
||||
import { pino, destination } from '../../pino.js'
|
||||
|
||||
test('named exports support', async () => {
|
||||
const stream = sink()
|
||||
const instance = pino(stream)
|
||||
instance.info('hello world')
|
||||
check(assert.equal, await once(stream, 'data'), 30, 'hello world')
|
||||
})
|
||||
|
||||
test('destination', async () => {
|
||||
const tmp = file()
|
||||
const instance = pino(destination(tmp))
|
||||
instance.info('hello')
|
||||
await watchFileCreated(tmp)
|
||||
const result = JSON.parse(readFileSync(tmp).toString())
|
||||
delete result.time
|
||||
assert.deepEqual(result, {
|
||||
pid: process.pid,
|
||||
hostname,
|
||||
level: 30,
|
||||
msg: 'hello'
|
||||
})
|
||||
})
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"_assert.js","sourceRoot":"","sources":["../src/_assert.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,MAAM,IAAI,EAAE,EACZ,OAAO,IAAI,EAAE,EACb,OAAO,IAAI,EAAE,EACb,OAAO,IAAI,EAAE,GAEd,MAAM,YAAY,CAAC;AACpB,8DAA8D;AAC9D,MAAM,CAAC,MAAM,MAAM,GAAc,EAAE,CAAC;AACpC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,OAAO,GAAc,EAAE,CAAC;AACrC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,OAAO,GAAc,EAAE,CAAC;AACrC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,OAAO,GAAc,EAAE,CAAC"}
|
||||
@@ -0,0 +1,134 @@
|
||||
"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 (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = default_1;
|
||||
const util = __importStar(require("../core/util.cjs"));
|
||||
const error = () => {
|
||||
const Sizable = {
|
||||
string: { unit: "àmi", verb: "ní" },
|
||||
file: { unit: "bytes", verb: "ní" },
|
||||
array: { unit: "nkan", verb: "ní" },
|
||||
set: { unit: "nkan", verb: "ní" },
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "ẹ̀rọ ìbáwọlé",
|
||||
email: "àdírẹ́sì ìmẹ́lì",
|
||||
url: "URL",
|
||||
emoji: "emoji",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "àkókò ISO",
|
||||
date: "ọjọ́ ISO",
|
||||
time: "àkókò ISO",
|
||||
duration: "àkókò tó pé ISO",
|
||||
ipv4: "àdírẹ́sì IPv4",
|
||||
ipv6: "àdírẹ́sì IPv6",
|
||||
cidrv4: "àgbègbè IPv4",
|
||||
cidrv6: "àgbègbè IPv6",
|
||||
base64: "ọ̀rọ̀ tí a kọ́ ní base64",
|
||||
base64url: "ọ̀rọ̀ base64url",
|
||||
json_string: "ọ̀rọ̀ JSON",
|
||||
e164: "nọ́mbà E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "ẹ̀rọ ìbáwọlé",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
number: "nọ́mbà",
|
||||
array: "akopọ",
|
||||
};
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `Ìbáwọlé aṣìṣe: a ní láti fi instanceof ${issue.expected}, àmọ̀ a rí ${received}`;
|
||||
}
|
||||
return `Ìbáwọlé aṣìṣe: a ní láti fi ${expected}, àmọ̀ a rí ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Ìbáwọlé aṣìṣe: a ní láti fi ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Àṣàyàn aṣìṣe: yan ọ̀kan lára ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Tó pọ̀ jù: a ní láti jẹ́ pé ${issue.origin ?? "iye"} ${sizing.verb} ${adj}${issue.maximum} ${sizing.unit}`;
|
||||
return `Tó pọ̀ jù: a ní láti jẹ́ ${adj}${issue.maximum}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Kéré ju: a ní láti jẹ́ pé ${issue.origin} ${sizing.verb} ${adj}${issue.minimum} ${sizing.unit}`;
|
||||
return `Kéré ju: a ní láti jẹ́ ${adj}${issue.minimum}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with")
|
||||
return `Ọ̀rọ̀ aṣìṣe: gbọ́dọ̀ bẹ̀rẹ̀ pẹ̀lú "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with")
|
||||
return `Ọ̀rọ̀ aṣìṣe: gbọ́dọ̀ parí pẹ̀lú "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes")
|
||||
return `Ọ̀rọ̀ aṣìṣe: gbọ́dọ̀ ní "${_issue.includes}"`;
|
||||
if (_issue.format === "regex")
|
||||
return `Ọ̀rọ̀ aṣìṣe: gbọ́dọ̀ bá àpẹẹrẹ mu ${_issue.pattern}`;
|
||||
return `Aṣìṣe: ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Nọ́mbà aṣìṣe: gbọ́dọ̀ jẹ́ èyà pípín ti ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `Bọtìnì àìmọ̀: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Bọtìnì aṣìṣe nínú ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Ìbáwọlé aṣìṣe";
|
||||
case "invalid_element":
|
||||
return `Iye aṣìṣe nínú ${issue.origin}`;
|
||||
default:
|
||||
return "Ìbáwọlé aṣìṣe";
|
||||
}
|
||||
};
|
||||
};
|
||||
function default_1() {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
module.exports = exports.default;
|
||||
@@ -0,0 +1,37 @@
|
||||
# @eslint-community/eslint-utils
|
||||
|
||||
[](https://www.npmjs.com/package/@eslint-community/eslint-utils)
|
||||
[](http://www.npmtrends.com/@eslint-community/eslint-utils)
|
||||
[](https://github.com/eslint-community/eslint-utils/actions)
|
||||
[](https://codecov.io/gh/eslint-community/eslint-utils)
|
||||
|
||||
## 🏁 Goal
|
||||
|
||||
This package provides utility functions and classes for make ESLint custom rules.
|
||||
|
||||
For examples:
|
||||
|
||||
- [`getStaticValue`](https://eslint-community.github.io/eslint-utils/api/ast-utils.html#getstaticvalue) evaluates static value on AST.
|
||||
- [`ReferenceTracker`](https://eslint-community.github.io/eslint-utils/api/scope-utils.html#referencetracker-class) checks the members of modules/globals as handling assignments and destructuring.
|
||||
|
||||
## 📖 Usage
|
||||
|
||||
See [documentation](https://eslint-community.github.io/eslint-utils).
|
||||
|
||||
## 📰 Changelog
|
||||
|
||||
See [releases](https://github.com/eslint-community/eslint-utils/releases).
|
||||
|
||||
## ❤️ Contributing
|
||||
|
||||
Welcome contributing!
|
||||
|
||||
Please use GitHub's Issues/PRs.
|
||||
|
||||
### Development Tools
|
||||
|
||||
- `npm run test-coverage` runs tests and measures coverage.
|
||||
- `npm run clean` removes the coverage result of `npm run test-coverage` command.
|
||||
- `npm run coverage` shows the coverage result of the last `npm run test-coverage` command.
|
||||
- `npm run lint` runs ESLint.
|
||||
- `npm run watch` runs tests on each file change.
|
||||
@@ -0,0 +1,15 @@
|
||||
The ISC License
|
||||
|
||||
Copyright (c) 2015, 2019 Elan Shanker, 2021 Blaine Bublitz <blaine.bublitz@gmail.com>, Eric Schoffstall <yo@contra.io> and other contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Config file for API Extractor. For more info, please visit: https://api-extractor.com
|
||||
*/
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
"extends": "../../scripts/api-extractor-base.json",
|
||||
"mainEntryPointFilePath": "<projectFolder>/dist/index.d.ts"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import 'node:fs';
|
||||
import 'node:url';
|
||||
import 'magic-string';
|
||||
export { a as automockModule } from './chunk-automock.js';
|
||||
import 'estree-walker';
|
||||
import 'node:module';
|
||||
import 'node:path';
|
||||
import './chunk-helpers.js';
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Pure function - doesn't mutate either parameter!
|
||||
* Uses the default options and overrides with the options provided by the user
|
||||
* @param defaultOptions the defaults
|
||||
* @param userOptions the user opts
|
||||
* @returns the options with defaults
|
||||
*/
|
||||
export declare function applyDefault<User extends readonly unknown[], Default extends User>(defaultOptions: Readonly<Default>, userOptions: Readonly<User> | null): Default;
|
||||
@@ -0,0 +1,4 @@
|
||||
function _arrayWithHoles(r) {
|
||||
if (Array.isArray(r)) return r;
|
||||
}
|
||||
export { _arrayWithHoles as default };
|
||||
@@ -0,0 +1,573 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
// ============================================================================
|
||||
// stringToNumber
|
||||
// ============================================================================
|
||||
|
||||
const stringToNumber = () =>
|
||||
z.codec(z.string(), z.number(), {
|
||||
decode: (str) => Number.parseFloat(str),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
|
||||
test("stringToNumber codec", () => {
|
||||
const codec = stringToNumber();
|
||||
|
||||
// Test decode
|
||||
expect(z.decode(codec, "42.5")).toBe(42.5);
|
||||
expect(z.decode(codec, "0")).toBe(0);
|
||||
expect(z.decode(codec, "-123.456")).toBe(-123.456);
|
||||
|
||||
// Test encode
|
||||
expect(z.encode(codec, 42.5)).toBe("42.5");
|
||||
expect(z.encode(codec, 0)).toBe("0");
|
||||
expect(z.encode(codec, -123.456)).toBe("-123.456");
|
||||
|
||||
// Test round trip
|
||||
const original = "3.14159";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("3.14159");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToInt
|
||||
// ============================================================================
|
||||
|
||||
const stringToInt = () =>
|
||||
z.codec(z.string(), z.int(), {
|
||||
decode: (str) => Number.parseInt(str, 10),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
|
||||
test("stringToInt codec", () => {
|
||||
const codec = stringToInt();
|
||||
|
||||
// Test decode
|
||||
expect(z.decode(codec, "42")).toBe(42);
|
||||
expect(z.decode(codec, "0")).toBe(0);
|
||||
expect(z.decode(codec, "-123")).toBe(-123);
|
||||
|
||||
// Test encode
|
||||
expect(z.encode(codec, 42)).toBe("42");
|
||||
expect(z.encode(codec, 0)).toBe("0");
|
||||
expect(z.encode(codec, -123)).toBe("-123");
|
||||
|
||||
// Test round trip
|
||||
const original = "999";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("999");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToBigInt
|
||||
// ============================================================================
|
||||
|
||||
const stringToBigInt = () =>
|
||||
z.codec(z.string(), z.bigint(), {
|
||||
decode: (str) => BigInt(str),
|
||||
encode: (bigint) => bigint.toString(),
|
||||
});
|
||||
|
||||
test("stringToBigInt codec", () => {
|
||||
const codec = stringToBigInt();
|
||||
|
||||
// Test decode
|
||||
expect(z.decode(codec, "123456789012345678901234567890")).toBe(123456789012345678901234567890n);
|
||||
expect(z.decode(codec, "0")).toBe(0n);
|
||||
expect(z.decode(codec, "-999")).toBe(-999n);
|
||||
|
||||
// Test encode
|
||||
expect(z.encode(codec, 123456789012345678901234567890n)).toBe("123456789012345678901234567890");
|
||||
expect(z.encode(codec, 0n)).toBe("0");
|
||||
expect(z.encode(codec, -999n)).toBe("-999");
|
||||
|
||||
// Test round trip
|
||||
const original = "987654321098765432109876543210";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("987654321098765432109876543210");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// numberToBigInt
|
||||
// ============================================================================
|
||||
|
||||
const numberToBigInt = () =>
|
||||
z.codec(z.int(), z.bigint(), {
|
||||
decode: (num) => BigInt(num),
|
||||
encode: (bigint) => Number(bigint),
|
||||
});
|
||||
|
||||
test("numberToBigInt codec", () => {
|
||||
const codec = numberToBigInt();
|
||||
|
||||
// Test decode
|
||||
expect(z.decode(codec, 42)).toBe(42n);
|
||||
expect(z.decode(codec, 0)).toBe(0n);
|
||||
expect(z.decode(codec, -123)).toBe(-123n);
|
||||
|
||||
// Test encode
|
||||
expect(z.encode(codec, 42n)).toBe(42);
|
||||
expect(z.encode(codec, 0n)).toBe(0);
|
||||
expect(z.encode(codec, -123n)).toBe(-123);
|
||||
|
||||
// Test round trip
|
||||
const original = 999;
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(999);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// isoDatetimeToDate
|
||||
// ============================================================================
|
||||
|
||||
const isoDatetimeToDate = () =>
|
||||
z.codec(z.iso.datetime(), z.date(), {
|
||||
decode: (isoString) => new Date(isoString),
|
||||
encode: (date) => date.toISOString(),
|
||||
});
|
||||
|
||||
test("isoDatetimeToDate codec", () => {
|
||||
const codec = isoDatetimeToDate();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "2024-01-15T10:30:00.000Z");
|
||||
expect(decoded).toBeInstanceOf(Date);
|
||||
expect(decoded.getTime()).toBe(1705314600000);
|
||||
|
||||
// Test encode
|
||||
const date = new Date("2024-01-15T10:30:00.000Z");
|
||||
expect(z.encode(codec, date)).toBe("2024-01-15T10:30:00.000Z");
|
||||
|
||||
// Test round trip
|
||||
const original = "2024-12-25T15:45:30.123Z";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("2024-12-25T15:45:30.123Z");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// epochSecondsToDate
|
||||
// ============================================================================
|
||||
|
||||
const epochSecondsToDate = () =>
|
||||
z.codec(z.int().min(0), z.date(), {
|
||||
decode: (seconds) => new Date(seconds * 1000),
|
||||
encode: (date) => Math.floor(date.getTime() / 1000),
|
||||
});
|
||||
|
||||
test("epochSecondsToDate codec", () => {
|
||||
const codec = epochSecondsToDate();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, 1705314600);
|
||||
expect(decoded).toBeInstanceOf(Date);
|
||||
expect(decoded.getTime()).toBe(1705314600000);
|
||||
|
||||
// Test encode
|
||||
const date = new Date(1705314600000);
|
||||
expect(z.encode(codec, date)).toBe(1705314600);
|
||||
|
||||
// Test round trip
|
||||
const original = 1640995200; // 2022-01-01 00:00:00 UTC
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(1640995200);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// epochMillisToDate
|
||||
// ============================================================================
|
||||
|
||||
const epochMillisToDate = () =>
|
||||
z.codec(z.int().min(0), z.date(), {
|
||||
decode: (millis) => new Date(millis),
|
||||
encode: (date) => date.getTime(),
|
||||
});
|
||||
|
||||
test("epochMillisToDate codec", () => {
|
||||
const codec = epochMillisToDate();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, 1705314600000);
|
||||
expect(decoded).toBeInstanceOf(Date);
|
||||
expect(decoded.getTime()).toBe(1705314600000);
|
||||
|
||||
// Test encode
|
||||
const date = new Date(1705314600000);
|
||||
expect(z.encode(codec, date)).toBe(1705314600000);
|
||||
|
||||
// Test round trip
|
||||
const original = 1640995200123; // 2022-01-01 00:00:00.123 UTC
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(1640995200123);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// json
|
||||
// ============================================================================
|
||||
|
||||
const jsonCodec = <T extends z.core.$ZodType>(schema: T) =>
|
||||
z.codec(z.string(), schema, {
|
||||
decode: (jsonString, ctx) => {
|
||||
try {
|
||||
return JSON.parse(jsonString);
|
||||
} catch (err: any) {
|
||||
ctx.issues.push({
|
||||
code: "invalid_format",
|
||||
format: "json",
|
||||
input: jsonString,
|
||||
message: err.message,
|
||||
});
|
||||
return z.NEVER;
|
||||
}
|
||||
},
|
||||
encode: (value) => JSON.stringify(value),
|
||||
});
|
||||
|
||||
test("json codec", () => {
|
||||
const codec = jsonCodec(z.object({ name: z.string(), age: z.number() }));
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, '{"name":"Alice","age":30}');
|
||||
expect(decoded).toEqual({ name: "Alice", age: 30 });
|
||||
|
||||
// Test encode
|
||||
const encoded = z.encode(codec, { name: "Bob", age: 25 });
|
||||
expect(encoded).toBe('{"name":"Bob","age":25}');
|
||||
|
||||
// Test round trip
|
||||
const original = '{"name":"Charlie","age":35}';
|
||||
const parsed = z.decode(codec, original);
|
||||
const roundTrip = z.encode(codec, parsed);
|
||||
expect(JSON.parse(roundTrip)).toEqual(JSON.parse(original));
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// utf8ToBytes
|
||||
// ============================================================================
|
||||
|
||||
const utf8ToBytes = () =>
|
||||
z.codec(z.string(), z.instanceof(Uint8Array), {
|
||||
decode: (str) => new TextEncoder().encode(str),
|
||||
encode: (bytes) => new TextDecoder().decode(bytes),
|
||||
});
|
||||
|
||||
test("utf8ToBytes codec", () => {
|
||||
const codec = utf8ToBytes();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "Hello, 世界!");
|
||||
expect(decoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(decoded)).toEqual([72, 101, 108, 108, 111, 44, 32, 228, 184, 150, 231, 149, 140, 33]);
|
||||
|
||||
// Test encode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
expect(z.encode(codec, bytes)).toBe("Hello");
|
||||
|
||||
// Test round trip
|
||||
const original = "Hello, 世界! 🚀";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// bytesToUtf8
|
||||
// ============================================================================
|
||||
|
||||
const bytesToUtf8 = () =>
|
||||
z.codec(z.instanceof(Uint8Array), z.string(), {
|
||||
decode: (bytes) => new TextDecoder().decode(bytes),
|
||||
encode: (str) => new TextEncoder().encode(str),
|
||||
});
|
||||
|
||||
test("bytesToUtf8 codec", () => {
|
||||
const codec = bytesToUtf8();
|
||||
|
||||
// Test decode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
const decoded = z.decode(codec, bytes);
|
||||
expect(decoded).toBe("Hello");
|
||||
|
||||
// Test encode
|
||||
const encoded = z.encode(codec, "Hello, 世界!");
|
||||
expect(encoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(encoded)).toEqual([72, 101, 108, 108, 111, 44, 32, 228, 184, 150, 231, 149, 140, 33]);
|
||||
|
||||
// Test round trip
|
||||
const original = new Uint8Array([72, 101, 108, 108, 111, 44, 32, 228, 184, 150, 231, 149, 140, 33]);
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toEqual(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// base64
|
||||
// ============================================================================
|
||||
|
||||
const base64 = () =>
|
||||
z.codec(z.base64(), z.instanceof(Uint8Array), {
|
||||
decode: (base64String) => z.util.base64ToUint8Array(base64String),
|
||||
encode: (bytes) => z.util.uint8ArrayToBase64(bytes),
|
||||
});
|
||||
|
||||
test("base64 codec", () => {
|
||||
const codec = base64();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "SGVsbG8=");
|
||||
expect(decoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(decoded)).toEqual([72, 101, 108, 108, 111]);
|
||||
|
||||
// Test encode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
expect(z.encode(codec, bytes)).toBe("SGVsbG8=");
|
||||
|
||||
// Test round trip
|
||||
const original = "SGVsbG8gV29ybGQh";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// base64urlToBytes
|
||||
// ============================================================================
|
||||
|
||||
const base64urlToBytes = () =>
|
||||
z.codec(z.base64url(), z.instanceof(Uint8Array), {
|
||||
decode: (base64urlString) => z.util.base64urlToUint8Array(base64urlString),
|
||||
encode: (bytes) => z.util.uint8ArrayToBase64url(bytes),
|
||||
});
|
||||
|
||||
test("base64urlToBytes codec", () => {
|
||||
const codec = base64urlToBytes();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "SGVsbG8");
|
||||
expect(decoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(decoded)).toEqual([72, 101, 108, 108, 111]);
|
||||
|
||||
// Test encode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
expect(z.encode(codec, bytes)).toBe("SGVsbG8");
|
||||
|
||||
// Test round trip with padding case
|
||||
const original = "SGVsbG9Xb3JsZA";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// hexToBytes
|
||||
// ============================================================================
|
||||
|
||||
const hexToBytes = () =>
|
||||
z.codec(z.hex(), z.instanceof(Uint8Array), {
|
||||
decode: (hexString) => z.util.hexToUint8Array(hexString),
|
||||
encode: (bytes) => z.util.uint8ArrayToHex(bytes),
|
||||
});
|
||||
|
||||
test("hexToBytes codec", () => {
|
||||
const codec = hexToBytes();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "48656c6c6f");
|
||||
expect(decoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(decoded)).toEqual([72, 101, 108, 108, 111]);
|
||||
|
||||
// Note: z.hex() doesn't accept 0x prefix, but our utility function can handle it
|
||||
// const decodedWithPrefix = z.decode(codec, "0x48656c6c6f");
|
||||
// expect(Array.from(decodedWithPrefix)).toEqual([72, 101, 108, 108, 111]);
|
||||
|
||||
// Test encode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
expect(z.encode(codec, bytes)).toBe("48656c6c6f");
|
||||
|
||||
// Test round trip
|
||||
const original = "deadbeef";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("deadbeef");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToURL
|
||||
// ============================================================================
|
||||
|
||||
const stringToURL = () =>
|
||||
z.codec(z.url(), z.instanceof(URL), {
|
||||
decode: (urlString) => new URL(urlString),
|
||||
encode: (url) => url.href,
|
||||
});
|
||||
|
||||
test("stringToURL codec", () => {
|
||||
const codec = stringToURL();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "https://example.com/path?query=value");
|
||||
expect(decoded).toBeInstanceOf(URL);
|
||||
expect(decoded.hostname).toBe("example.com");
|
||||
expect(decoded.pathname).toBe("/path");
|
||||
expect(decoded.search).toBe("?query=value");
|
||||
|
||||
// Test encode
|
||||
const url = new URL("https://example.com/path?query=value");
|
||||
expect(z.encode(codec, url)).toBe("https://example.com/path?query=value");
|
||||
|
||||
// Test round trip
|
||||
const original = "https://test.com/api/v1?foo=bar&baz=qux";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToHttpURL
|
||||
// ============================================================================
|
||||
|
||||
const stringToHttpURL = () =>
|
||||
z.codec(z.httpUrl(), z.instanceof(URL), {
|
||||
decode: (urlString) => new URL(urlString),
|
||||
encode: (url) => url.href,
|
||||
});
|
||||
|
||||
test("stringToHttpURL codec", () => {
|
||||
const codec = stringToHttpURL();
|
||||
|
||||
// Test decode HTTPS
|
||||
const decodedHttps = z.decode(codec, "https://example.com/path");
|
||||
expect(decodedHttps).toBeInstanceOf(URL);
|
||||
expect(decodedHttps.protocol).toBe("https:");
|
||||
|
||||
// Test decode HTTP
|
||||
const decodedHttp = z.decode(codec, "http://example.com/path");
|
||||
expect(decodedHttp).toBeInstanceOf(URL);
|
||||
expect(decodedHttp.protocol).toBe("http:");
|
||||
|
||||
// Test encode
|
||||
const url = new URL("https://example.com/path");
|
||||
expect(z.encode(codec, url)).toBe("https://example.com/path");
|
||||
|
||||
// Test round trip
|
||||
const original = "http://api.example.com/v1/users";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// uriComponent
|
||||
// ============================================================================
|
||||
|
||||
const uriComponent = () =>
|
||||
z.codec(z.string(), z.string(), {
|
||||
decode: (encodedString) => decodeURIComponent(encodedString),
|
||||
encode: (decodedString) => encodeURIComponent(decodedString),
|
||||
});
|
||||
|
||||
test("uriComponent codec", () => {
|
||||
const codec = uriComponent();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "Hello%20World%21");
|
||||
expect(decoded).toBe("Hello World!");
|
||||
|
||||
// Test encode
|
||||
const encoded = z.encode(codec, "Hello World!");
|
||||
expect(encoded).toBe("Hello%20World!");
|
||||
|
||||
// Test round trip
|
||||
const original = "Hello%20World%21%20%26%20More";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("Hello%20World!%20%26%20More");
|
||||
|
||||
// Test complex characters
|
||||
const complex = "café & résumé";
|
||||
const encodedComplex = z.encode(codec, complex);
|
||||
const decodedComplex = z.decode(codec, encodedComplex);
|
||||
expect(decodedComplex).toBe(complex);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToBoolean
|
||||
// ============================================================================
|
||||
|
||||
const stringToBoolean = (options?: { truthy?: string[]; falsy?: string[] }) => z.stringbool(options);
|
||||
|
||||
test("stringToBoolean codec", () => {
|
||||
const codec = stringToBoolean();
|
||||
|
||||
// Test decode - default truthy values
|
||||
expect(z.decode(codec, "true")).toBe(true);
|
||||
expect(z.decode(codec, "yes")).toBe(true);
|
||||
expect(z.decode(codec, "1")).toBe(true);
|
||||
|
||||
// Test decode - default falsy values
|
||||
expect(z.decode(codec, "false")).toBe(false);
|
||||
expect(z.decode(codec, "no")).toBe(false);
|
||||
expect(z.decode(codec, "0")).toBe(false);
|
||||
|
||||
// Test encode - default behavior
|
||||
expect(z.encode(codec, true)).toBe("true");
|
||||
expect(z.encode(codec, false)).toBe("false");
|
||||
|
||||
// Test custom options
|
||||
const customCodec = stringToBoolean({ truthy: ["yes", "y"], falsy: ["no", "n"] });
|
||||
expect(z.decode(customCodec, "yes")).toBe(true);
|
||||
expect(z.decode(customCodec, "y")).toBe(true);
|
||||
expect(z.decode(customCodec, "no")).toBe(false);
|
||||
expect(z.decode(customCodec, "n")).toBe(false);
|
||||
expect(z.encode(customCodec, true)).toBe("yes");
|
||||
expect(z.encode(customCodec, false)).toBe("no");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Error Handling Tests
|
||||
// ============================================================================
|
||||
|
||||
// Test error cases - these test input validation, not transform errors
|
||||
test("codec input validation", () => {
|
||||
// Test invalid base64 format
|
||||
const base64Codec = base64();
|
||||
const invalidBase64Result = z.safeDecode(base64Codec, "invalid!@#");
|
||||
expect(invalidBase64Result.success).toBe(false);
|
||||
|
||||
// Test invalid hex format
|
||||
const hexCodec = hexToBytes();
|
||||
const invalidHexResult = z.safeDecode(hexCodec, "gg");
|
||||
expect(invalidHexResult.success).toBe(false);
|
||||
|
||||
// Test invalid URL format
|
||||
const urlCodec = stringToURL();
|
||||
const invalidUrlResult = z.safeDecode(urlCodec, "not a url");
|
||||
expect(invalidUrlResult.success).toBe(false);
|
||||
|
||||
// Test invalid HTTP URL format
|
||||
const httpUrlCodec = stringToHttpURL();
|
||||
const invalidHttpResult = z.safeDecode(httpUrlCodec, "ftp://example.com");
|
||||
expect(invalidHttpResult.success).toBe(false);
|
||||
});
|
||||
|
||||
// Test transform errors - these test errors added by transform functions
|
||||
test("codec transform error handling", () => {
|
||||
// JSON codec that can fail during transform
|
||||
const anyJSON = jsonCodec(z.json());
|
||||
|
||||
// Test successful JSON parsing
|
||||
const validResult = z.safeDecode(anyJSON, '{"valid": "json"}');
|
||||
expect(validResult.success).toBe(true);
|
||||
if (validResult.success) {
|
||||
expect(validResult.data).toEqual({ valid: "json" });
|
||||
}
|
||||
|
||||
// Test invalid JSON that should create a single "invalid_format" issue
|
||||
// Verifies that the transform error aborts before reaching the output schema
|
||||
const invalidResult = z.safeDecode(anyJSON, '{"invalid":,}');
|
||||
expect(invalidResult.success).toBe(false);
|
||||
if (!invalidResult.success) {
|
||||
expect(invalidResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "json",
|
||||
"message": "Unexpected token ',', "{"invalid":,}" is not valid JSON",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import type { TSESTree } from '@typescript-eslint/types';
|
||||
import type { Definition } from '../definition';
|
||||
import type { Reference } from '../referencer/Reference';
|
||||
import type { Scope } from '../scope';
|
||||
export declare class VariableBase {
|
||||
/**
|
||||
* A unique ID for this instance - primarily used to help debugging and testing
|
||||
*/
|
||||
readonly $id: number;
|
||||
/**
|
||||
* The array of the definitions of this variable.
|
||||
* @public
|
||||
*/
|
||||
readonly defs: Definition[];
|
||||
/**
|
||||
* True if the variable is considered used for the purposes of `no-unused-vars`, false otherwise.
|
||||
* @public
|
||||
*/
|
||||
eslintUsed: boolean;
|
||||
/**
|
||||
* The array of `Identifier` nodes which define this variable.
|
||||
* If this variable is redeclared, this array includes two or more nodes.
|
||||
* @public
|
||||
*/
|
||||
readonly identifiers: TSESTree.Identifier[];
|
||||
/**
|
||||
* The variable name, as given in the source code.
|
||||
* @public
|
||||
*/
|
||||
readonly name: string;
|
||||
/**
|
||||
* List of {@link Reference} of this variable (excluding parameter entries) in its defining scope and all nested scopes.
|
||||
* For defining occurrences only see {@link Variable#defs}.
|
||||
* @public
|
||||
*/
|
||||
readonly references: Reference[];
|
||||
/**
|
||||
* Reference to the enclosing Scope.
|
||||
*/
|
||||
readonly scope: Scope;
|
||||
constructor(name: string, scope: Scope);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const lib: LibDefinition;
|
||||
@@ -0,0 +1,460 @@
|
||||
import { SolanaError, SOLANA_ERROR__CODECS__EXPECTED_FIXED_LENGTH, SOLANA_ERROR__CODECS__EXPECTED_VARIABLE_LENGTH, SOLANA_ERROR__CODECS__ENCODER_DECODER_SIZE_COMPATIBILITY_MISMATCH, SOLANA_ERROR__CODECS__ENCODER_DECODER_FIXED_SIZE_MISMATCH, SOLANA_ERROR__CODECS__ENCODER_DECODER_MAX_SIZE_MISMATCH, SOLANA_ERROR__CODECS__CANNOT_DECODE_EMPTY_BYTE_ARRAY, SOLANA_ERROR__CODECS__INVALID_BYTE_LENGTH, SOLANA_ERROR__CODECS__OFFSET_OUT_OF_RANGE, SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, SOLANA_ERROR__CODECS__SENTINEL_MISSING_IN_DECODED_BYTES, SOLANA_ERROR__CODECS__ENCODED_BYTES_MUST_NOT_INCLUDE_SENTINEL } from '@solana/errors';
|
||||
|
||||
// src/add-codec-sentinel.ts
|
||||
|
||||
// src/bytes.ts
|
||||
var mergeBytes = (byteArrays) => {
|
||||
const nonEmptyByteArrays = byteArrays.filter((arr) => arr.length);
|
||||
if (nonEmptyByteArrays.length === 0) {
|
||||
return byteArrays.length ? byteArrays[0] : new Uint8Array();
|
||||
}
|
||||
if (nonEmptyByteArrays.length === 1) {
|
||||
return nonEmptyByteArrays[0];
|
||||
}
|
||||
const totalLength = nonEmptyByteArrays.reduce((total, arr) => total + arr.length, 0);
|
||||
const result = new Uint8Array(totalLength);
|
||||
let offset = 0;
|
||||
nonEmptyByteArrays.forEach((arr) => {
|
||||
result.set(arr, offset);
|
||||
offset += arr.length;
|
||||
});
|
||||
return result;
|
||||
};
|
||||
var padBytes = (bytes, length) => {
|
||||
if (bytes.length >= length) return bytes;
|
||||
const paddedBytes = new Uint8Array(length).fill(0);
|
||||
paddedBytes.set(bytes);
|
||||
return paddedBytes;
|
||||
};
|
||||
var fixBytes = (bytes, length) => padBytes(bytes.length <= length ? bytes : bytes.slice(0, length), length);
|
||||
function containsBytes(data, bytes, offset) {
|
||||
const slice = offset === 0 && data.length === bytes.length ? data : data.slice(offset, offset + bytes.length);
|
||||
if (slice.length !== bytes.length) return false;
|
||||
return bytes.every((b, i) => b === slice[i]);
|
||||
}
|
||||
function getEncodedSize(value, encoder) {
|
||||
return "fixedSize" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);
|
||||
}
|
||||
function createEncoder(encoder) {
|
||||
return Object.freeze({
|
||||
...encoder,
|
||||
encode: (value) => {
|
||||
const bytes = new Uint8Array(getEncodedSize(value, encoder));
|
||||
encoder.write(value, bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function createDecoder(decoder) {
|
||||
return Object.freeze({
|
||||
...decoder,
|
||||
decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0]
|
||||
});
|
||||
}
|
||||
function createCodec(codec) {
|
||||
return Object.freeze({
|
||||
...codec,
|
||||
decode: (bytes, offset = 0) => codec.read(bytes, offset)[0],
|
||||
encode: (value) => {
|
||||
const bytes = new Uint8Array(getEncodedSize(value, codec));
|
||||
codec.write(value, bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function isFixedSize(codec) {
|
||||
return "fixedSize" in codec && typeof codec.fixedSize === "number";
|
||||
}
|
||||
function assertIsFixedSize(codec) {
|
||||
if (!isFixedSize(codec)) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__EXPECTED_FIXED_LENGTH);
|
||||
}
|
||||
}
|
||||
function isVariableSize(codec) {
|
||||
return !isFixedSize(codec);
|
||||
}
|
||||
function assertIsVariableSize(codec) {
|
||||
if (!isVariableSize(codec)) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__EXPECTED_VARIABLE_LENGTH);
|
||||
}
|
||||
}
|
||||
function combineCodec(encoder, decoder) {
|
||||
if (isFixedSize(encoder) !== isFixedSize(decoder)) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__ENCODER_DECODER_SIZE_COMPATIBILITY_MISMATCH);
|
||||
}
|
||||
if (isFixedSize(encoder) && isFixedSize(decoder) && encoder.fixedSize !== decoder.fixedSize) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__ENCODER_DECODER_FIXED_SIZE_MISMATCH, {
|
||||
decoderFixedSize: decoder.fixedSize,
|
||||
encoderFixedSize: encoder.fixedSize
|
||||
});
|
||||
}
|
||||
if (!isFixedSize(encoder) && !isFixedSize(decoder) && encoder.maxSize !== decoder.maxSize) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__ENCODER_DECODER_MAX_SIZE_MISMATCH, {
|
||||
decoderMaxSize: decoder.maxSize,
|
||||
encoderMaxSize: encoder.maxSize
|
||||
});
|
||||
}
|
||||
return {
|
||||
...decoder,
|
||||
...encoder,
|
||||
decode: decoder.decode,
|
||||
encode: encoder.encode,
|
||||
read: decoder.read,
|
||||
write: encoder.write
|
||||
};
|
||||
}
|
||||
|
||||
// src/add-codec-sentinel.ts
|
||||
function addEncoderSentinel(encoder, sentinel) {
|
||||
const write = (value, bytes, offset) => {
|
||||
const encoderBytes = encoder.encode(value);
|
||||
if (findSentinelIndex(encoderBytes, sentinel) >= 0) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__ENCODED_BYTES_MUST_NOT_INCLUDE_SENTINEL, {
|
||||
encodedBytes: encoderBytes,
|
||||
hexEncodedBytes: hexBytes(encoderBytes),
|
||||
hexSentinel: hexBytes(sentinel),
|
||||
sentinel
|
||||
});
|
||||
}
|
||||
bytes.set(encoderBytes, offset);
|
||||
offset += encoderBytes.length;
|
||||
bytes.set(sentinel, offset);
|
||||
offset += sentinel.length;
|
||||
return offset;
|
||||
};
|
||||
if (isFixedSize(encoder)) {
|
||||
return createEncoder({ ...encoder, fixedSize: encoder.fixedSize + sentinel.length, write });
|
||||
}
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
...encoder.maxSize != null ? { maxSize: encoder.maxSize + sentinel.length } : {},
|
||||
getSizeFromValue: (value) => encoder.getSizeFromValue(value) + sentinel.length,
|
||||
write
|
||||
});
|
||||
}
|
||||
function addDecoderSentinel(decoder, sentinel) {
|
||||
const read = (bytes, offset) => {
|
||||
const candidateBytes = offset === 0 ? bytes : bytes.slice(offset);
|
||||
const sentinelIndex = findSentinelIndex(candidateBytes, sentinel);
|
||||
if (sentinelIndex === -1) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__SENTINEL_MISSING_IN_DECODED_BYTES, {
|
||||
decodedBytes: candidateBytes,
|
||||
hexDecodedBytes: hexBytes(candidateBytes),
|
||||
hexSentinel: hexBytes(sentinel),
|
||||
sentinel
|
||||
});
|
||||
}
|
||||
const preSentinelBytes = candidateBytes.slice(0, sentinelIndex);
|
||||
return [decoder.decode(preSentinelBytes), offset + preSentinelBytes.length + sentinel.length];
|
||||
};
|
||||
if (isFixedSize(decoder)) {
|
||||
return createDecoder({ ...decoder, fixedSize: decoder.fixedSize + sentinel.length, read });
|
||||
}
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
...decoder.maxSize != null ? { maxSize: decoder.maxSize + sentinel.length } : {},
|
||||
read
|
||||
});
|
||||
}
|
||||
function addCodecSentinel(codec, sentinel) {
|
||||
return combineCodec(addEncoderSentinel(codec, sentinel), addDecoderSentinel(codec, sentinel));
|
||||
}
|
||||
function findSentinelIndex(bytes, sentinel) {
|
||||
return bytes.findIndex((byte, index, arr) => {
|
||||
if (sentinel.length === 1) return byte === sentinel[0];
|
||||
return containsBytes(arr, sentinel, index);
|
||||
});
|
||||
}
|
||||
function hexBytes(bytes) {
|
||||
return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
|
||||
}
|
||||
function assertByteArrayIsNotEmptyForCodec(codecDescription, bytes, offset = 0) {
|
||||
if (bytes.length - offset <= 0) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__CANNOT_DECODE_EMPTY_BYTE_ARRAY, {
|
||||
codecDescription
|
||||
});
|
||||
}
|
||||
}
|
||||
function assertByteArrayHasEnoughBytesForCodec(codecDescription, expected, bytes, offset = 0) {
|
||||
const bytesLength = bytes.length - offset;
|
||||
if (bytesLength < expected) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__INVALID_BYTE_LENGTH, {
|
||||
bytesLength,
|
||||
codecDescription,
|
||||
expected
|
||||
});
|
||||
}
|
||||
}
|
||||
function assertByteArrayOffsetIsNotOutOfRange(codecDescription, offset, bytesLength) {
|
||||
if (offset < 0 || offset > bytesLength) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__OFFSET_OUT_OF_RANGE, {
|
||||
bytesLength,
|
||||
codecDescription,
|
||||
offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// src/add-codec-size-prefix.ts
|
||||
function addEncoderSizePrefix(encoder, prefix) {
|
||||
const write = (value, bytes, offset) => {
|
||||
const encoderBytes = encoder.encode(value);
|
||||
offset = prefix.write(encoderBytes.length, bytes, offset);
|
||||
bytes.set(encoderBytes, offset);
|
||||
return offset + encoderBytes.length;
|
||||
};
|
||||
if (isFixedSize(prefix) && isFixedSize(encoder)) {
|
||||
return createEncoder({ ...encoder, fixedSize: prefix.fixedSize + encoder.fixedSize, write });
|
||||
}
|
||||
const prefixMaxSize = isFixedSize(prefix) ? prefix.fixedSize : prefix.maxSize ?? null;
|
||||
const encoderMaxSize = isFixedSize(encoder) ? encoder.fixedSize : encoder.maxSize ?? null;
|
||||
const maxSize = prefixMaxSize !== null && encoderMaxSize !== null ? prefixMaxSize + encoderMaxSize : null;
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
...maxSize !== null ? { maxSize } : {},
|
||||
getSizeFromValue: (value) => {
|
||||
const encoderSize = getEncodedSize(value, encoder);
|
||||
return getEncodedSize(encoderSize, prefix) + encoderSize;
|
||||
},
|
||||
write
|
||||
});
|
||||
}
|
||||
function addDecoderSizePrefix(decoder, prefix) {
|
||||
const read = (bytes, offset) => {
|
||||
const [bigintSize, decoderOffset] = prefix.read(bytes, offset);
|
||||
const size = Number(bigintSize);
|
||||
offset = decoderOffset;
|
||||
if (offset > 0 || bytes.length > size) {
|
||||
bytes = bytes.slice(offset, offset + size);
|
||||
}
|
||||
assertByteArrayHasEnoughBytesForCodec("addDecoderSizePrefix", size, bytes);
|
||||
return [decoder.decode(bytes), offset + size];
|
||||
};
|
||||
if (isFixedSize(prefix) && isFixedSize(decoder)) {
|
||||
return createDecoder({ ...decoder, fixedSize: prefix.fixedSize + decoder.fixedSize, read });
|
||||
}
|
||||
const prefixMaxSize = isFixedSize(prefix) ? prefix.fixedSize : prefix.maxSize ?? null;
|
||||
const decoderMaxSize = isFixedSize(decoder) ? decoder.fixedSize : decoder.maxSize ?? null;
|
||||
const maxSize = prefixMaxSize !== null && decoderMaxSize !== null ? prefixMaxSize + decoderMaxSize : null;
|
||||
return createDecoder({ ...decoder, ...maxSize !== null ? { maxSize } : {}, read });
|
||||
}
|
||||
function addCodecSizePrefix(codec, prefix) {
|
||||
return combineCodec(addEncoderSizePrefix(codec, prefix), addDecoderSizePrefix(codec, prefix));
|
||||
}
|
||||
|
||||
// src/fix-codec-size.ts
|
||||
function fixEncoderSize(encoder, fixedBytes) {
|
||||
return createEncoder({
|
||||
fixedSize: fixedBytes,
|
||||
write: (value, bytes, offset) => {
|
||||
const variableByteArray = encoder.encode(value);
|
||||
const fixedByteArray = variableByteArray.length > fixedBytes ? variableByteArray.slice(0, fixedBytes) : variableByteArray;
|
||||
bytes.set(fixedByteArray, offset);
|
||||
return offset + fixedBytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function fixDecoderSize(decoder, fixedBytes) {
|
||||
return createDecoder({
|
||||
fixedSize: fixedBytes,
|
||||
read: (bytes, offset) => {
|
||||
assertByteArrayHasEnoughBytesForCodec("fixCodecSize", fixedBytes, bytes, offset);
|
||||
if (offset > 0 || bytes.length > fixedBytes) {
|
||||
bytes = bytes.slice(offset, offset + fixedBytes);
|
||||
}
|
||||
if (isFixedSize(decoder)) {
|
||||
bytes = fixBytes(bytes, decoder.fixedSize);
|
||||
}
|
||||
const [value] = decoder.read(bytes, 0);
|
||||
return [value, offset + fixedBytes];
|
||||
}
|
||||
});
|
||||
}
|
||||
function fixCodecSize(codec, fixedBytes) {
|
||||
return combineCodec(fixEncoderSize(codec, fixedBytes), fixDecoderSize(codec, fixedBytes));
|
||||
}
|
||||
|
||||
// src/offset-codec.ts
|
||||
function offsetEncoder(encoder, config) {
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
write: (value, bytes, preOffset) => {
|
||||
const wrapBytes = (offset) => modulo(offset, bytes.length);
|
||||
const newPreOffset = config.preOffset ? config.preOffset({ bytes, preOffset, wrapBytes }) : preOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetEncoder", newPreOffset, bytes.length);
|
||||
const postOffset = encoder.write(value, bytes, newPreOffset);
|
||||
const newPostOffset = config.postOffset ? config.postOffset({ bytes, newPreOffset, postOffset, preOffset, wrapBytes }) : postOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetEncoder", newPostOffset, bytes.length);
|
||||
return newPostOffset;
|
||||
}
|
||||
});
|
||||
}
|
||||
function offsetDecoder(decoder, config) {
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, preOffset) => {
|
||||
const wrapBytes = (offset) => modulo(offset, bytes.length);
|
||||
const newPreOffset = config.preOffset ? config.preOffset({ bytes, preOffset, wrapBytes }) : preOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetDecoder", newPreOffset, bytes.length);
|
||||
const [value, postOffset] = decoder.read(bytes, newPreOffset);
|
||||
const newPostOffset = config.postOffset ? config.postOffset({ bytes, newPreOffset, postOffset, preOffset, wrapBytes }) : postOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetDecoder", newPostOffset, bytes.length);
|
||||
return [value, newPostOffset];
|
||||
}
|
||||
});
|
||||
}
|
||||
function offsetCodec(codec, config) {
|
||||
return combineCodec(offsetEncoder(codec, config), offsetDecoder(codec, config));
|
||||
}
|
||||
function modulo(dividend, divisor) {
|
||||
if (divisor === 0) return 0;
|
||||
return (dividend % divisor + divisor) % divisor;
|
||||
}
|
||||
function resizeEncoder(encoder, resize) {
|
||||
if (isFixedSize(encoder)) {
|
||||
const fixedSize = resize(encoder.fixedSize);
|
||||
if (fixedSize < 0) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: fixedSize,
|
||||
codecDescription: "resizeEncoder"
|
||||
});
|
||||
}
|
||||
return createEncoder({ ...encoder, fixedSize });
|
||||
}
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
getSizeFromValue: (value) => {
|
||||
const newSize = resize(encoder.getSizeFromValue(value));
|
||||
if (newSize < 0) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: newSize,
|
||||
codecDescription: "resizeEncoder"
|
||||
});
|
||||
}
|
||||
return newSize;
|
||||
}
|
||||
});
|
||||
}
|
||||
function resizeDecoder(decoder, resize) {
|
||||
if (isFixedSize(decoder)) {
|
||||
const fixedSize = resize(decoder.fixedSize);
|
||||
if (fixedSize < 0) {
|
||||
throw new SolanaError(SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: fixedSize,
|
||||
codecDescription: "resizeDecoder"
|
||||
});
|
||||
}
|
||||
return createDecoder({ ...decoder, fixedSize });
|
||||
}
|
||||
return decoder;
|
||||
}
|
||||
function resizeCodec(codec, resize) {
|
||||
return combineCodec(resizeEncoder(codec, resize), resizeDecoder(codec, resize));
|
||||
}
|
||||
|
||||
// src/pad-codec.ts
|
||||
function padLeftEncoder(encoder, offset) {
|
||||
return offsetEncoder(
|
||||
resizeEncoder(encoder, (size) => size + offset),
|
||||
{ preOffset: ({ preOffset }) => preOffset + offset }
|
||||
);
|
||||
}
|
||||
function padRightEncoder(encoder, offset) {
|
||||
return offsetEncoder(
|
||||
resizeEncoder(encoder, (size) => size + offset),
|
||||
{ postOffset: ({ postOffset }) => postOffset + offset }
|
||||
);
|
||||
}
|
||||
function padLeftDecoder(decoder, offset) {
|
||||
return offsetDecoder(
|
||||
resizeDecoder(decoder, (size) => size + offset),
|
||||
{ preOffset: ({ preOffset }) => preOffset + offset }
|
||||
);
|
||||
}
|
||||
function padRightDecoder(decoder, offset) {
|
||||
return offsetDecoder(
|
||||
resizeDecoder(decoder, (size) => size + offset),
|
||||
{ postOffset: ({ postOffset }) => postOffset + offset }
|
||||
);
|
||||
}
|
||||
function padLeftCodec(codec, offset) {
|
||||
return combineCodec(padLeftEncoder(codec, offset), padLeftDecoder(codec, offset));
|
||||
}
|
||||
function padRightCodec(codec, offset) {
|
||||
return combineCodec(padRightEncoder(codec, offset), padRightDecoder(codec, offset));
|
||||
}
|
||||
|
||||
// src/reverse-codec.ts
|
||||
function copySourceToTargetInReverse(source, target_WILL_MUTATE, sourceOffset, sourceLength, targetOffset = 0) {
|
||||
while (sourceOffset < --sourceLength) {
|
||||
const leftValue = source[sourceOffset];
|
||||
target_WILL_MUTATE[sourceOffset + targetOffset] = source[sourceLength];
|
||||
target_WILL_MUTATE[sourceLength + targetOffset] = leftValue;
|
||||
sourceOffset++;
|
||||
}
|
||||
if (sourceOffset === sourceLength) {
|
||||
target_WILL_MUTATE[sourceOffset + targetOffset] = source[sourceOffset];
|
||||
}
|
||||
}
|
||||
function reverseEncoder(encoder) {
|
||||
assertIsFixedSize(encoder);
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
write: (value, bytes, offset) => {
|
||||
const newOffset = encoder.write(value, bytes, offset);
|
||||
copySourceToTargetInReverse(
|
||||
bytes,
|
||||
bytes,
|
||||
offset,
|
||||
offset + encoder.fixedSize
|
||||
);
|
||||
return newOffset;
|
||||
}
|
||||
});
|
||||
}
|
||||
function reverseDecoder(decoder) {
|
||||
assertIsFixedSize(decoder);
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, offset) => {
|
||||
const reversedBytes = bytes.slice();
|
||||
copySourceToTargetInReverse(
|
||||
bytes,
|
||||
reversedBytes,
|
||||
offset,
|
||||
offset + decoder.fixedSize
|
||||
);
|
||||
return decoder.read(reversedBytes, offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
function reverseCodec(codec) {
|
||||
return combineCodec(reverseEncoder(codec), reverseDecoder(codec));
|
||||
}
|
||||
|
||||
// src/transform-codec.ts
|
||||
function transformEncoder(encoder, unmap) {
|
||||
return createEncoder({
|
||||
...isVariableSize(encoder) ? { ...encoder, getSizeFromValue: (value) => encoder.getSizeFromValue(unmap(value)) } : encoder,
|
||||
write: (value, bytes, offset) => encoder.write(unmap(value), bytes, offset)
|
||||
});
|
||||
}
|
||||
function transformDecoder(decoder, map) {
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, offset) => {
|
||||
const [value, newOffset] = decoder.read(bytes, offset);
|
||||
return [map(value, bytes, offset), newOffset];
|
||||
}
|
||||
});
|
||||
}
|
||||
function transformCodec(codec, unmap, map) {
|
||||
return createCodec({
|
||||
...transformEncoder(codec, unmap),
|
||||
read: map ? transformDecoder(codec, map).read : codec.read
|
||||
});
|
||||
}
|
||||
|
||||
export { addCodecSentinel, addCodecSizePrefix, addDecoderSentinel, addDecoderSizePrefix, addEncoderSentinel, addEncoderSizePrefix, assertByteArrayHasEnoughBytesForCodec, assertByteArrayIsNotEmptyForCodec, assertByteArrayOffsetIsNotOutOfRange, assertIsFixedSize, assertIsVariableSize, combineCodec, containsBytes, createCodec, createDecoder, createEncoder, fixBytes, fixCodecSize, fixDecoderSize, fixEncoderSize, getEncodedSize, isFixedSize, isVariableSize, mergeBytes, offsetCodec, offsetDecoder, offsetEncoder, padBytes, padLeftCodec, padLeftDecoder, padLeftEncoder, padRightCodec, padRightDecoder, padRightEncoder, resizeCodec, resizeDecoder, resizeEncoder, reverseCodec, reverseDecoder, reverseEncoder, transformCodec, transformDecoder, transformEncoder };
|
||||
//# sourceMappingURL=index.native.mjs.map
|
||||
//# sourceMappingURL=index.native.mjs.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"blake2b.d.ts","sourceRoot":"","sources":["src/blake2b.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,aAAa,CAAC;AAC7D,+DAA+D;AAC/D,eAAO,MAAM,OAAO,EAAE,OAAO,GAAS,CAAC;AACvC,+DAA+D;AAC/D,eAAO,MAAM,OAAO,EAAE,OAAO,GAAS,CAAC"}
|
||||
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/json-schema-secure.json#",
|
||||
"title": "Meta-schema for the security assessment of JSON Schemas",
|
||||
"description": "If a JSON Schema fails validation against this meta-schema, it may be unsafe to validate untrusted data",
|
||||
"definitions": {
|
||||
"schemaArray": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {"$ref": "#"}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"patternProperties": {
|
||||
"description": "prevent slow validation of large property names",
|
||||
"required": ["propertyNames"],
|
||||
"properties": {
|
||||
"propertyNames": {
|
||||
"required": ["maxLength"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"uniqueItems": {
|
||||
"description": "prevent slow validation of large non-scalar arrays",
|
||||
"if": {
|
||||
"properties": {
|
||||
"uniqueItems": {"const": true},
|
||||
"items": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"anyOf": [
|
||||
{
|
||||
"enum": ["object", "array"]
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"contains": {"enum": ["object", "array"]}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": ["maxItems"]
|
||||
}
|
||||
},
|
||||
"pattern": {
|
||||
"description": "prevent slow pattern matching of large strings",
|
||||
"required": ["maxLength"]
|
||||
},
|
||||
"format": {
|
||||
"description": "prevent slow format validation of large strings",
|
||||
"required": ["maxLength"]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"additionalItems": {"$ref": "#"},
|
||||
"additionalProperties": {"$ref": "#"},
|
||||
"dependencies": {
|
||||
"additionalProperties": {
|
||||
"anyOf": [
|
||||
{"type": "array"},
|
||||
{"$ref": "#"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{"$ref": "#"},
|
||||
{"$ref": "#/definitions/schemaArray"}
|
||||
]
|
||||
},
|
||||
"definitions": {
|
||||
"additionalProperties": {"$ref": "#"}
|
||||
},
|
||||
"patternProperties": {
|
||||
"additionalProperties": {"$ref": "#"}
|
||||
},
|
||||
"properties": {
|
||||
"additionalProperties": {"$ref": "#"}
|
||||
},
|
||||
"if": {"$ref": "#"},
|
||||
"then": {"$ref": "#"},
|
||||
"else": {"$ref": "#"},
|
||||
"allOf": {"$ref": "#/definitions/schemaArray"},
|
||||
"anyOf": {"$ref": "#/definitions/schemaArray"},
|
||||
"oneOf": {"$ref": "#/definitions/schemaArray"},
|
||||
"not": {"$ref": "#"},
|
||||
"contains": {"$ref": "#"},
|
||||
"propertyNames": {"$ref": "#"}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getTextWithParentheses = getTextWithParentheses;
|
||||
const _1 = require(".");
|
||||
function getTextWithParentheses(sourceCode, node) {
|
||||
// Capture parentheses before and after the node
|
||||
let beforeCount = 0;
|
||||
let afterCount = 0;
|
||||
if ((0, _1.isParenthesized)(node, sourceCode)) {
|
||||
const bodyOpeningParen = (0, _1.nullThrows)(sourceCode.getTokenBefore(node, _1.isOpeningParenToken), _1.NullThrowsReasons.MissingToken('(', 'node'));
|
||||
const bodyClosingParen = (0, _1.nullThrows)(sourceCode.getTokenAfter(node, _1.isClosingParenToken), _1.NullThrowsReasons.MissingToken(')', 'node'));
|
||||
beforeCount = node.range[0] - bodyOpeningParen.range[0];
|
||||
afterCount = bodyClosingParen.range[1] - node.range[1];
|
||||
}
|
||||
return sourceCode.getText(node, beforeCount, afterCount);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { c as logParseError, d as getCodeFrame, n as error, t as augmentCodeLocation, u as locate } from "./shared/logs-DmYCAKcW.mjs";
|
||||
import { n as parseSync, t as parse } from "./shared/parse-DnWvq9XZ.mjs";
|
||||
//#region src/parse-ast-index.ts
|
||||
function wrap(result, filename, sourceText) {
|
||||
if (result.errors.length > 0) return normalizeParseError(filename, sourceText, result.errors);
|
||||
return result.program;
|
||||
}
|
||||
function normalizeParseError(filename, sourceText, errors) {
|
||||
let message = `Parse failed with ${errors.length} error${errors.length < 2 ? "" : "s"}:\n`;
|
||||
const pos = errors[0]?.labels?.[0]?.start;
|
||||
for (let i = 0; i < errors.length; i++) {
|
||||
if (i >= 5) {
|
||||
message += "\n...";
|
||||
break;
|
||||
}
|
||||
const e = errors[i];
|
||||
message += e.message + "\n" + e.labels.map((label) => {
|
||||
const location = locate(sourceText, label.start, { offsetLine: 1 });
|
||||
if (!location) return;
|
||||
return getCodeFrame(sourceText, location.line, location.column);
|
||||
}).filter(Boolean).join("\n");
|
||||
}
|
||||
const log = logParseError(message, filename, pos);
|
||||
if (pos !== void 0 && filename) augmentCodeLocation(log, pos, sourceText, filename);
|
||||
return error(log);
|
||||
}
|
||||
const defaultParserOptions = {
|
||||
lang: "js",
|
||||
preserveParens: false
|
||||
};
|
||||
/**
|
||||
* Parse code synchronously and return the AST.
|
||||
*
|
||||
* This function is similar to Rollup's `parseAst` function.
|
||||
* Prefer using {@linkcode parseSync} instead of this function as it has more information in the return value.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
function parseAst(sourceText, options, filename) {
|
||||
return wrap(parseSync(filename ?? "file.js", sourceText, {
|
||||
...defaultParserOptions,
|
||||
...options
|
||||
}), filename, sourceText);
|
||||
}
|
||||
/**
|
||||
* Parse code asynchronously and return the AST.
|
||||
*
|
||||
* This function is similar to Rollup's `parseAstAsync` function.
|
||||
* Prefer using {@linkcode parseAsync} instead of this function as it has more information in the return value.
|
||||
*
|
||||
* @category Utilities
|
||||
*/
|
||||
async function parseAstAsync(sourceText, options, filename) {
|
||||
return wrap(await parse(filename ?? "file.js", sourceText, {
|
||||
...defaultParserOptions,
|
||||
...options
|
||||
}), filename, sourceText);
|
||||
}
|
||||
//#endregion
|
||||
export { parseAst, parseAstAsync };
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"tokenFlags.enum.d.ts","sourceRoot":"","sources":["../../src/enums/tokenFlags.enum.ts"],"names":[],"mappings":"AAEA,oBAAY,UAAU;IAClB,IAAI,IAAI;IACR,kBAAkB,IAAS;IAC3B,qBAAqB,IAAS;IAC9B,YAAY,IAAS;IACrB,qBAAqB,IAAS;IAC9B,UAAU,KAAS;IACnB,KAAK,KAAS;IACd,YAAY,KAAS;IACrB,eAAe,MAAS;IACxB,cAAc,MAAS;IACvB,iBAAiB,MAAS;IAC1B,aAAa,OAAU;IACvB,qBAAqB,OAAU;IAC/B,SAAS,OAAU;IACnB,mBAAmB,OAAU;IAC7B,wBAAwB,QAAU;IAClC,8BAA8B,QAAU;IACxC,WAAW,QAAU;IACrB,4BAA4B,SAAU;IACtC,2BAA2B,SAAU;IACrC,sBAAsB,MAAmC;IACzD,aAAa,MAAwC;IACrD,kBAAkB,QAAyG;IAC3H,mBAAmB,QAA0G;IAC7H,wBAAwB,OAA2F;IACnH,6BAA6B,IAAe;IAC5C,SAAS,QAAiF;CAC7F"}
|
||||
@@ -0,0 +1,438 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
// Utility functions
|
||||
function expectMethodMatch(schema: z.ZodType, params?: z.core.ToJSONSchemaParams): void {
|
||||
const staticResult = z.toJSONSchema(schema, params);
|
||||
const methodResult = schema.toJSONSchema(params);
|
||||
expect(methodResult).toEqual(staticResult);
|
||||
}
|
||||
|
||||
describe("toJSONSchema method", () => {
|
||||
describe("primitive types", () => {
|
||||
test("string", () => {
|
||||
expectMethodMatch(z.string());
|
||||
});
|
||||
|
||||
test("number", () => {
|
||||
expectMethodMatch(z.number());
|
||||
});
|
||||
|
||||
test("boolean", () => {
|
||||
expectMethodMatch(z.boolean());
|
||||
});
|
||||
|
||||
test("bigint", () => {
|
||||
expectMethodMatch(z.bigint(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("symbol", () => {
|
||||
expectMethodMatch(z.symbol(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("null", () => {
|
||||
expectMethodMatch(z.null());
|
||||
});
|
||||
|
||||
test("undefined", () => {
|
||||
expectMethodMatch(z.undefined(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("void", () => {
|
||||
expectMethodMatch(z.void(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("never", () => {
|
||||
expectMethodMatch(z.never());
|
||||
});
|
||||
|
||||
test("any", () => {
|
||||
expectMethodMatch(z.any());
|
||||
});
|
||||
|
||||
test("unknown", () => {
|
||||
expectMethodMatch(z.unknown());
|
||||
});
|
||||
|
||||
test("date", () => {
|
||||
expectMethodMatch(z.date(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("nan", () => {
|
||||
expectMethodMatch(z.nan(), { unrepresentable: "any" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("string formats", () => {
|
||||
test("email", () => {
|
||||
expectMethodMatch(z.email());
|
||||
});
|
||||
|
||||
test("url", () => {
|
||||
expectMethodMatch(z.url());
|
||||
});
|
||||
|
||||
test("uuid", () => {
|
||||
expectMethodMatch(z.uuid());
|
||||
});
|
||||
|
||||
test("datetime", () => {
|
||||
expectMethodMatch(z.iso.datetime());
|
||||
});
|
||||
|
||||
test("date", () => {
|
||||
expectMethodMatch(z.iso.date());
|
||||
});
|
||||
|
||||
test("guid", () => {
|
||||
expectMethodMatch(z.guid());
|
||||
});
|
||||
|
||||
test("cuid", () => {
|
||||
expectMethodMatch(z.cuid());
|
||||
});
|
||||
|
||||
test("cuid2", () => {
|
||||
expectMethodMatch(z.cuid2());
|
||||
});
|
||||
|
||||
test("ulid", () => {
|
||||
expectMethodMatch(z.ulid());
|
||||
});
|
||||
|
||||
test("base64", () => {
|
||||
expectMethodMatch(z.base64());
|
||||
});
|
||||
|
||||
test("ipv4", () => {
|
||||
expectMethodMatch(z.ipv4());
|
||||
});
|
||||
|
||||
test("ipv6", () => {
|
||||
expectMethodMatch(z.ipv6());
|
||||
});
|
||||
});
|
||||
|
||||
describe("string validations", () => {
|
||||
test("min length", () => {
|
||||
expectMethodMatch(z.string().min(5));
|
||||
});
|
||||
|
||||
test("max length", () => {
|
||||
expectMethodMatch(z.string().max(10));
|
||||
});
|
||||
|
||||
test("length", () => {
|
||||
expectMethodMatch(z.string().length(5));
|
||||
});
|
||||
|
||||
test("regex", () => {
|
||||
expectMethodMatch(z.string().regex(/^[A-Z]+$/));
|
||||
});
|
||||
|
||||
test("multiple patterns", () => {
|
||||
expectMethodMatch(
|
||||
z
|
||||
.string()
|
||||
.regex(/^[A-Z]+$/)
|
||||
.regex(/^[0-9]+$/)
|
||||
);
|
||||
});
|
||||
|
||||
test("startsWith", () => {
|
||||
expectMethodMatch(z.string().startsWith("hello"));
|
||||
});
|
||||
|
||||
test("endsWith", () => {
|
||||
expectMethodMatch(z.string().endsWith("world"));
|
||||
});
|
||||
|
||||
test("includes", () => {
|
||||
expectMethodMatch(z.string().includes("test"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("number validations", () => {
|
||||
test("min", () => {
|
||||
expectMethodMatch(z.number().min(5));
|
||||
});
|
||||
|
||||
test("max", () => {
|
||||
expectMethodMatch(z.number().max(10));
|
||||
});
|
||||
|
||||
test("int", () => {
|
||||
expectMethodMatch(z.int());
|
||||
});
|
||||
|
||||
test("positive", () => {
|
||||
expectMethodMatch(z.number().positive());
|
||||
});
|
||||
|
||||
test("negative", () => {
|
||||
expectMethodMatch(z.number().negative());
|
||||
});
|
||||
|
||||
test("multipleOf", () => {
|
||||
expectMethodMatch(z.number().multipleOf(2));
|
||||
});
|
||||
|
||||
test("gte", () => {
|
||||
expectMethodMatch(z.number().gte(5));
|
||||
});
|
||||
|
||||
test("lte", () => {
|
||||
expectMethodMatch(z.number().lte(10));
|
||||
});
|
||||
|
||||
test("gt", () => {
|
||||
expectMethodMatch(z.number().gt(5));
|
||||
});
|
||||
|
||||
test("lt", () => {
|
||||
expectMethodMatch(z.number().lt(10));
|
||||
});
|
||||
});
|
||||
|
||||
describe("literals and enums", () => {
|
||||
test("literal string", () => {
|
||||
expectMethodMatch(z.literal("hello"));
|
||||
});
|
||||
|
||||
test("literal number", () => {
|
||||
expectMethodMatch(z.literal(42));
|
||||
});
|
||||
|
||||
test("literal boolean", () => {
|
||||
expectMethodMatch(z.literal(true));
|
||||
});
|
||||
|
||||
test("literal null", () => {
|
||||
expectMethodMatch(z.literal(null));
|
||||
});
|
||||
|
||||
test("multiple literals", () => {
|
||||
expectMethodMatch(z.literal(["a", "b", "c"]));
|
||||
});
|
||||
|
||||
test("enum", () => {
|
||||
expectMethodMatch(z.enum(["red", "green", "blue"]));
|
||||
});
|
||||
|
||||
test("nativeEnum", () => {
|
||||
enum Colors {
|
||||
Red = "red",
|
||||
Green = "green",
|
||||
Blue = "blue",
|
||||
}
|
||||
expectMethodMatch(z.nativeEnum(Colors));
|
||||
});
|
||||
});
|
||||
|
||||
describe("composite types", () => {
|
||||
test("array", () => {
|
||||
expectMethodMatch(z.array(z.string()));
|
||||
});
|
||||
|
||||
test("array with min", () => {
|
||||
expectMethodMatch(z.array(z.string()).min(2));
|
||||
});
|
||||
|
||||
test("array with max", () => {
|
||||
expectMethodMatch(z.array(z.string()).max(10));
|
||||
});
|
||||
|
||||
test("object", () => {
|
||||
expectMethodMatch(z.object({ name: z.string(), age: z.number() }));
|
||||
});
|
||||
|
||||
test("object with optional", () => {
|
||||
expectMethodMatch(z.object({ name: z.string(), age: z.number().optional() }));
|
||||
});
|
||||
|
||||
test("strict object", () => {
|
||||
expectMethodMatch(z.strictObject({ name: z.string() }));
|
||||
});
|
||||
|
||||
test("loose object", () => {
|
||||
expectMethodMatch(z.looseObject({ name: z.string() }));
|
||||
});
|
||||
|
||||
test("object with catchall", () => {
|
||||
expectMethodMatch(z.object({ name: z.string() }).catchall(z.string()));
|
||||
});
|
||||
|
||||
test("tuple", () => {
|
||||
expectMethodMatch(z.tuple([z.string(), z.number()]));
|
||||
});
|
||||
|
||||
test("tuple with rest", () => {
|
||||
expectMethodMatch(z.tuple([z.string()], z.number()));
|
||||
});
|
||||
|
||||
test("record", () => {
|
||||
expectMethodMatch(z.record(z.string(), z.number()));
|
||||
});
|
||||
|
||||
test("union", () => {
|
||||
expectMethodMatch(z.union([z.string(), z.number()]));
|
||||
});
|
||||
|
||||
test("discriminated union", () => {
|
||||
expectMethodMatch(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), value: z.string() }),
|
||||
z.object({ type: z.literal("b"), value: z.number() }),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
test("intersection", () => {
|
||||
expectMethodMatch(z.intersection(z.object({ a: z.string() }), z.object({ b: z.number() })));
|
||||
});
|
||||
});
|
||||
|
||||
describe("wrapper types", () => {
|
||||
test("optional", () => {
|
||||
expectMethodMatch(z.string().optional());
|
||||
});
|
||||
|
||||
test("nullable", () => {
|
||||
expectMethodMatch(z.string().nullable());
|
||||
});
|
||||
|
||||
test("nullish", () => {
|
||||
expectMethodMatch(z.string().nullish());
|
||||
});
|
||||
|
||||
test("default", () => {
|
||||
expectMethodMatch(z.string().default("hello"));
|
||||
});
|
||||
|
||||
test("default function", () => {
|
||||
expectMethodMatch(z.string().default(() => "hello"));
|
||||
});
|
||||
|
||||
test("prefault", () => {
|
||||
expectMethodMatch(z.string().prefault("hello"));
|
||||
});
|
||||
|
||||
test("prefault function", () => {
|
||||
expectMethodMatch(z.string().prefault(() => "hello"));
|
||||
});
|
||||
|
||||
test("catch", () => {
|
||||
expectMethodMatch(z.string().catch("hello"));
|
||||
});
|
||||
|
||||
test("readonly", () => {
|
||||
expectMethodMatch(z.string().readonly());
|
||||
});
|
||||
|
||||
test("nonoptional", () => {
|
||||
expectMethodMatch(z.string().optional().nonoptional());
|
||||
});
|
||||
});
|
||||
|
||||
describe("special types", () => {
|
||||
test("lazy", () => {
|
||||
type Node = {
|
||||
value: string;
|
||||
children?: Node[] | undefined;
|
||||
};
|
||||
const Node: z.ZodType<Node> = z.lazy(() =>
|
||||
z.object({
|
||||
value: z.string(),
|
||||
children: z.array(Node).optional(),
|
||||
})
|
||||
) as z.ZodType<Node>;
|
||||
expectMethodMatch(Node);
|
||||
});
|
||||
|
||||
test("promise", () => {
|
||||
expectMethodMatch(z.promise(z.string()));
|
||||
});
|
||||
|
||||
test("pipe", () => {
|
||||
expectMethodMatch(
|
||||
z
|
||||
.string()
|
||||
.transform((val) => val.length)
|
||||
.pipe(z.number())
|
||||
);
|
||||
});
|
||||
|
||||
test("transform", () => {
|
||||
expectMethodMatch(
|
||||
z.string().transform((val) => val.length),
|
||||
{ unrepresentable: "any" }
|
||||
);
|
||||
});
|
||||
|
||||
test("file", () => {
|
||||
expectMethodMatch(z.file());
|
||||
});
|
||||
|
||||
test("file with mime", () => {
|
||||
expectMethodMatch(z.file().mime("image/png"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("parameters", () => {
|
||||
test("target draft-7", () => {
|
||||
expectMethodMatch(z.string(), { target: "draft-7" });
|
||||
});
|
||||
|
||||
test("target draft-4", () => {
|
||||
expectMethodMatch(z.string(), { target: "draft-4" });
|
||||
});
|
||||
|
||||
test("target openapi-3.0", () => {
|
||||
expectMethodMatch(z.string(), { target: "openapi-3.0" });
|
||||
});
|
||||
|
||||
test("io input", () => {
|
||||
expectMethodMatch(z.string().default("hello"), { io: "input" });
|
||||
});
|
||||
|
||||
test("cycles throw", () => {
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(schema);
|
||||
},
|
||||
});
|
||||
// Both should throw the same error
|
||||
expect(() => z.toJSONSchema(schema, { cycles: "throw" })).toThrow();
|
||||
expect(() => schema.toJSONSchema({ cycles: "throw" })).toThrow();
|
||||
});
|
||||
|
||||
test("reused ref", () => {
|
||||
const shared = z.string();
|
||||
const schema = z.object({
|
||||
a: shared,
|
||||
b: shared,
|
||||
});
|
||||
expectMethodMatch(schema, { reused: "ref" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("edge cases with metadata", () => {
|
||||
test("schema with id metadata", () => {
|
||||
const a = z.string().meta({ id: "hi" });
|
||||
expectMethodMatch(a);
|
||||
});
|
||||
|
||||
test("schema with id then additional metadata", () => {
|
||||
const a = z.string().meta({ id: "hi2" });
|
||||
const b = a.meta({ name: "asdf" });
|
||||
expectMethodMatch(b);
|
||||
});
|
||||
|
||||
test("nested schema with id", () => {
|
||||
const inner = z.string().meta({ id: "inner" });
|
||||
const outer = z.object({ value: inner });
|
||||
expectMethodMatch(outer);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
let Stringifier = require('./stringifier')
|
||||
|
||||
function stringify(node, builder) {
|
||||
let str = new Stringifier(builder)
|
||||
str.stringify(node)
|
||||
}
|
||||
|
||||
module.exports = stringify
|
||||
stringify.default = stringify
|
||||
@@ -0,0 +1,14 @@
|
||||
/// <reference path="../../typings/thenable.d.ts" preserve="true" />
|
||||
import { Message, MessageSignature, RequestMessage, RequestType, RequestType0, RequestType1, RequestType2, RequestType3, RequestType4, RequestType5, RequestType6, RequestType7, RequestType8, RequestType9, ResponseError, ErrorCodes, NotificationMessage, NotificationType, NotificationType0, NotificationType1, NotificationType2, NotificationType3, NotificationType4, NotificationType5, NotificationType6, NotificationType7, NotificationType8, NotificationType9, ResponseMessage, ParameterStructures, _EM } from './messages';
|
||||
import { LinkedMap, LRUCache, Touch } from './linkedMap';
|
||||
import { Disposable } from './disposable';
|
||||
import { Event, Emitter } from './events';
|
||||
import { AbstractCancellationTokenSource, CancellationTokenSource, CancellationToken } from './cancellation';
|
||||
import { SharedArraySenderStrategy, SharedArrayReceiverStrategy } from './sharedArrayCancellation';
|
||||
import { MessageReader, AbstractMessageReader, ReadableStreamMessageReader, DataCallback, MessageReaderOptions, PartialMessageInfo } from './messageReader';
|
||||
import { MessageWriter, AbstractMessageWriter, WriteableStreamMessageWriter, MessageWriterOptions } from './messageWriter';
|
||||
import { AbstractMessageBuffer } from './messageBuffer';
|
||||
import { ContentTypeEncoderOptions, ContentEncoder, ContentTypeEncoder, ContentTypeDecoderOptions, ContentDecoder, ContentTypeDecoder } from './encoding';
|
||||
import { Logger, ConnectionStrategy, ConnectionOptions, MessageConnection, NullLogger, createMessageConnection, ProgressToken, ProgressType, RequestParam, HandlerResult, StarRequestHandler, GenericRequestHandler, RequestHandler0, RequestHandler, RequestHandler1, RequestHandler2, RequestHandler3, RequestHandler4, RequestHandler5, RequestHandler6, RequestHandler7, RequestHandler8, RequestHandler9, StarNotificationHandler, GenericNotificationHandler, NotificationHandler0, NotificationHandler, NotificationHandler1, NotificationHandler2, NotificationHandler3, NotificationHandler4, NotificationHandler5, NotificationHandler6, NotificationHandler7, NotificationHandler8, NotificationHandler9, Trace, TraceValue, TraceFormat, TraceOptions, SetTraceParams, SetTraceNotification, LogTraceParams, LogTraceNotification, Tracer, ConnectionErrors, ConnectionError, CancellationId, CancellationReceiverStrategy, IdCancellationReceiverStrategy, RequestCancellationReceiverStrategy, CancellationSenderStrategy, CancellationStrategy, MessageStrategy, TraceValues } from './connection';
|
||||
import RAL from './ral';
|
||||
export { RAL, Message, MessageSignature, RequestMessage, RequestType, RequestType0, RequestType1, RequestType2, RequestType3, RequestType4, RequestType5, RequestType6, RequestType7, RequestType8, RequestType9, ResponseError, ErrorCodes, NotificationMessage, NotificationType, NotificationType0, NotificationType1, NotificationType2, NotificationType3, NotificationType4, NotificationType5, NotificationType6, NotificationType7, NotificationType8, NotificationType9, ResponseMessage, ParameterStructures, _EM, LinkedMap, Touch, LRUCache, Disposable, Event, Emitter, AbstractCancellationTokenSource, CancellationTokenSource, CancellationToken, SharedArraySenderStrategy, SharedArrayReceiverStrategy, MessageReader, AbstractMessageReader, ReadableStreamMessageReader, DataCallback, MessageReaderOptions, PartialMessageInfo, MessageWriter, AbstractMessageWriter, WriteableStreamMessageWriter, MessageWriterOptions, AbstractMessageBuffer, ContentTypeEncoderOptions, ContentEncoder, ContentTypeEncoder, ContentTypeDecoderOptions, ContentDecoder, ContentTypeDecoder, Logger, ConnectionStrategy, ConnectionOptions, MessageConnection, NullLogger, createMessageConnection, ProgressToken, ProgressType, RequestParam, HandlerResult, StarRequestHandler, GenericRequestHandler, RequestHandler0, RequestHandler, RequestHandler1, RequestHandler2, RequestHandler3, RequestHandler4, RequestHandler5, RequestHandler6, RequestHandler7, RequestHandler8, RequestHandler9, StarNotificationHandler, GenericNotificationHandler, NotificationHandler0, NotificationHandler, NotificationHandler1, NotificationHandler2, NotificationHandler3, NotificationHandler4, NotificationHandler5, NotificationHandler6, NotificationHandler7, NotificationHandler8, NotificationHandler9, Trace, TraceValue, TraceValues, TraceFormat, TraceOptions, SetTraceParams, SetTraceNotification, LogTraceParams, LogTraceNotification, Tracer, ConnectionErrors, ConnectionError, CancellationId, CancellationReceiverStrategy, IdCancellationReceiverStrategy, RequestCancellationReceiverStrategy, CancellationSenderStrategy, CancellationStrategy, MessageStrategy };
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,18 @@
|
||||
export * from './builtinSymbolLikes';
|
||||
export * from './containsAllTypesByName';
|
||||
export * from './getConstrainedTypeAtLocation';
|
||||
export * from './getContextualType';
|
||||
export * from './getDeclaration';
|
||||
export * from './getSourceFileOfNode';
|
||||
export * from './getTypeName';
|
||||
export * from './isSymbolFromDefaultLibrary';
|
||||
export * from './isTypeBrandedLiteralLike';
|
||||
export * from './isTypeReadonly';
|
||||
export * from './isUnsafeAssignment';
|
||||
export * from './predicates';
|
||||
export * from './propertyTypes';
|
||||
export * from './requiresQuoting';
|
||||
export * from './typeFlagUtils';
|
||||
export * from './TypeOrValueSpecifier';
|
||||
export * from './discriminateAnyType';
|
||||
export { getDecorators, getModifiers, typescriptVersionIsAtLeast, } from '@typescript-eslint/typescript-estree';
|
||||
@@ -0,0 +1,70 @@
|
||||
'use strict'
|
||||
|
||||
let pico = require('picocolors')
|
||||
|
||||
let tokenizer = require('./tokenize')
|
||||
|
||||
let Input
|
||||
|
||||
function registerInput(dependant) {
|
||||
Input = dependant
|
||||
}
|
||||
|
||||
const HIGHLIGHT_THEME = {
|
||||
';': pico.yellow,
|
||||
':': pico.yellow,
|
||||
'(': pico.cyan,
|
||||
')': pico.cyan,
|
||||
'[': pico.yellow,
|
||||
']': pico.yellow,
|
||||
'{': pico.yellow,
|
||||
'}': pico.yellow,
|
||||
'at-word': pico.cyan,
|
||||
'brackets': pico.cyan,
|
||||
'call': pico.cyan,
|
||||
'class': pico.yellow,
|
||||
'comment': pico.gray,
|
||||
'hash': pico.magenta,
|
||||
'string': pico.green
|
||||
}
|
||||
|
||||
function getTokenType([type, value], processor) {
|
||||
if (type === 'word') {
|
||||
if (value[0] === '.') {
|
||||
return 'class'
|
||||
}
|
||||
if (value[0] === '#') {
|
||||
return 'hash'
|
||||
}
|
||||
}
|
||||
|
||||
if (!processor.endOfFile()) {
|
||||
let next = processor.nextToken()
|
||||
processor.back(next)
|
||||
if (next[0] === 'brackets' || next[0] === '(') return 'call'
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
|
||||
function terminalHighlight(css) {
|
||||
let processor = tokenizer(new Input(css), { ignoreErrors: true })
|
||||
let result = ''
|
||||
while (!processor.endOfFile()) {
|
||||
let token = processor.nextToken()
|
||||
let color = HIGHLIGHT_THEME[getTokenType(token, processor)]
|
||||
if (color) {
|
||||
result += token[1]
|
||||
.split(/\r?\n/)
|
||||
.map(i => color(i))
|
||||
.join('\n')
|
||||
} else {
|
||||
result += token[1]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
terminalHighlight.registerInput = registerInput
|
||||
|
||||
module.exports = terminalHighlight
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"scriptTarget.d.ts","sourceRoot":"","sources":["../../src/enums/scriptTarget.ts"],"names":[],"mappings":"AAAA,eAAO,IAAI,YAAY,EAAE,GAAG,CAAC"}
|
||||
@@ -0,0 +1,28 @@
|
||||
'use strict'
|
||||
|
||||
const { defineConfig, globalIgnores } = require('eslint/config')
|
||||
const neostandard = require('neostandard')
|
||||
|
||||
module.exports = defineConfig([
|
||||
neostandard({
|
||||
ts: true
|
||||
}),
|
||||
globalIgnores([
|
||||
'pino.d.ts',
|
||||
'test/fixtures/syntax-error-esm.mjs',
|
||||
'test/fixtures/ts/*cjs',
|
||||
]),
|
||||
{
|
||||
rules: {
|
||||
'no-var': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['test/types/**/*'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-expressions': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'n/handle-callback-err': 'off',
|
||||
},
|
||||
},
|
||||
])
|
||||
@@ -0,0 +1,34 @@
|
||||
# postgres-bytea [](https://travis-ci.org/bendrucker/postgres-bytea)
|
||||
|
||||
> Postgres bytea parser
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save postgres-bytea
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var bytea = require('postgres-bytea');
|
||||
bytea('\\000\\100\\200')
|
||||
//=> buffer
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
#### `bytea(input)` -> `buffer`
|
||||
|
||||
##### input
|
||||
|
||||
*Required*
|
||||
Type: `string`
|
||||
|
||||
A Postgres bytea binary string.
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Ben Drucker](http://bendrucker.me)
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"legacy.d.ts","sourceRoot":"","sources":["../src/legacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAO,MAAM,EAAO,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,KAAK,KAAK,EAA6B,MAAM,YAAY,CAAC;AAUnE,8BAA8B;AAC9B,qBAAa,IAAK,SAAQ,MAAM,CAAC,IAAI,CAAC;IACpC,OAAO,CAAC,CAAC,CAAkB;IAC3B,OAAO,CAAC,CAAC,CAAkB;IAC3B,OAAO,CAAC,CAAC,CAAkB;IAC3B,OAAO,CAAC,CAAC,CAAkB;IAC3B,OAAO,CAAC,CAAC,CAAkB;;IAK3B,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAIzD,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAO1E,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAoCvD,SAAS,CAAC,UAAU,IAAI,IAAI;IAG5B,OAAO,IAAI,IAAI;CAIhB;AAED,6EAA6E;AAC7E,eAAO,MAAM,IAAI,EAAE,KAAsD,CAAC;AAa1E,6BAA6B;AAC7B,qBAAa,GAAI,SAAQ,MAAM,CAAC,GAAG,CAAC;IAClC,OAAO,CAAC,CAAC,CAAiB;IAC1B,OAAO,CAAC,CAAC,CAAiB;IAC1B,OAAO,CAAC,CAAC,CAAiB;IAC1B,OAAO,CAAC,CAAC,CAAiB;;IAK1B,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAIjD,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAM/D,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAoCvD,SAAS,CAAC,UAAU,IAAI,IAAI;IAG5B,OAAO,IAAI,IAAI;CAIhB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG,EAAE,KAAqD,CAAC;AA6CxE,qBAAa,SAAU,SAAQ,MAAM,CAAC,SAAS,CAAC;IAC9C,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,EAAE,CAAkB;;IAK5B,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAIzD,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAO/E,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAmCvD,SAAS,CAAC,UAAU,IAAI,IAAI;IAG5B,OAAO,IAAI,IAAI;CAKhB;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,KAA2D,CAAC"}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "@types/ws",
|
||||
"version": "7.4.7",
|
||||
"description": "TypeScript definitions for ws",
|
||||
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ws",
|
||||
"license": "MIT",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Paul Loyd",
|
||||
"url": "https://github.com/loyd",
|
||||
"githubUsername": "loyd"
|
||||
},
|
||||
{
|
||||
"name": "Margus Lamp",
|
||||
"url": "https://github.com/mlamp",
|
||||
"githubUsername": "mlamp"
|
||||
},
|
||||
{
|
||||
"name": "Philippe D'Alva",
|
||||
"url": "https://github.com/TitaneBoy",
|
||||
"githubUsername": "TitaneBoy"
|
||||
},
|
||||
{
|
||||
"name": "reduckted",
|
||||
"url": "https://github.com/reduckted",
|
||||
"githubUsername": "reduckted"
|
||||
},
|
||||
{
|
||||
"name": "teidesu",
|
||||
"url": "https://github.com/teidesu",
|
||||
"githubUsername": "teidesu"
|
||||
},
|
||||
{
|
||||
"name": "Bartosz Wojtkowiak",
|
||||
"url": "https://github.com/wojtkowiak",
|
||||
"githubUsername": "wojtkowiak"
|
||||
},
|
||||
{
|
||||
"name": "Kyle Hensel",
|
||||
"url": "https://github.com/k-yle",
|
||||
"githubUsername": "k-yle"
|
||||
}
|
||||
],
|
||||
"main": "",
|
||||
"types": "index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||
"directory": "types/ws"
|
||||
},
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
},
|
||||
"typesPublisherContentHash": "bfa5f3d19c5c1f1c415aec2e218c5c83c4c88b441bb05b2c022b6cfee2c36dfd",
|
||||
"typeScriptVersion": "3.6"
|
||||
}
|
||||
Reference in New Issue
Block a user