full site update
This commit is contained in:
21
node_modules/destr/LICENSE
generated
vendored
Normal file
21
node_modules/destr/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Pooya Parsa <pooya@pi0.io>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
132
node_modules/destr/README.md
generated
vendored
Normal file
132
node_modules/destr/README.md
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
# destr
|
||||
|
||||
[![npm version][npm-version-src]][npm-version-href]
|
||||
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
||||
[![bundle][bundle-src]][bundle-href]
|
||||
[![License][license-src]][license-href]
|
||||
|
||||
A faster, secure and convenient alternative for [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
|
||||
|
||||
## Usage
|
||||
|
||||
### Node.js
|
||||
|
||||
Install dependency:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm i destr
|
||||
|
||||
# yarn
|
||||
yarn add destr
|
||||
|
||||
# pnpm
|
||||
pnpm i destr
|
||||
```
|
||||
|
||||
Import into your Node.js project:
|
||||
|
||||
```js
|
||||
// ESM
|
||||
import { destr, safeDestr } from "destr";
|
||||
|
||||
// CommonJS
|
||||
const { destr, safeDestr } = require("destr");
|
||||
```
|
||||
|
||||
### Deno
|
||||
|
||||
```js
|
||||
import { destr, safeDestr } from "https://deno.land/x/destr/src/index.ts";
|
||||
|
||||
console.log(destr('{ "deno": "yay" }'));
|
||||
```
|
||||
|
||||
## Why?
|
||||
|
||||
### ✅ Type Safe
|
||||
|
||||
```ts
|
||||
const obj = JSON.parse("{}"); // obj type is any
|
||||
|
||||
const obj = destr("{}"); // obj type is unknown by default
|
||||
|
||||
const obj = destr<MyInterface>("{}"); // obj is well-typed
|
||||
```
|
||||
|
||||
### ✅ Fast fallback to input if is not string
|
||||
|
||||
```js
|
||||
// Uncaught SyntaxError: Unexpected token u in JSON at position 0
|
||||
JSON.parse();
|
||||
|
||||
// undefined
|
||||
destr();
|
||||
```
|
||||
|
||||
### ✅ Fast lookup for known string values
|
||||
|
||||
```js
|
||||
// Uncaught SyntaxError: Unexpected token T in JSON at position 0
|
||||
JSON.parse("TRUE");
|
||||
|
||||
// true
|
||||
destr("TRUE");
|
||||
```
|
||||
|
||||
### ✅ Fallback to original value if parse fails (empty or any plain string)
|
||||
|
||||
```js
|
||||
// Uncaught SyntaxError: Unexpected token s in JSON at position 0
|
||||
JSON.parse("salam");
|
||||
|
||||
// "salam"
|
||||
destr("salam");
|
||||
```
|
||||
|
||||
**Note:** This fails in safe/strict mode with `safeDestr`.
|
||||
|
||||
### ✅ Avoid prototype pollution
|
||||
|
||||
```js
|
||||
const input = '{ "user": { "__proto__": { "isAdmin": true } } }';
|
||||
|
||||
// { user: { __proto__: { isAdmin: true } } }
|
||||
JSON.parse(input);
|
||||
|
||||
// { user: {} }
|
||||
destr(input);
|
||||
```
|
||||
|
||||
### ✅ Strict Mode
|
||||
|
||||
When using `safeDestr` it will throw an error if the input is not a valid JSON string or parsing fails. (non string values and built-ins will be still returned as-is)
|
||||
|
||||
```js
|
||||
// Returns "[foo"
|
||||
destr("[foo");
|
||||
|
||||
// Throws an error
|
||||
safeDestr("[foo");
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
`destr` is faster generally for arbitrary inputs but also sometimes little bit slower than `JSON.parse` when parsing a valid JSON string mainly because of transform to avoid [prototype pollution](https://learn.snyk.io/lessons/prototype-pollution/javascript/) which can lead to serious security issues if not being sanitized. In the other words, `destr` is better when input is not always a JSON string or from untrusted source like request body.
|
||||
|
||||
Check [Benchmark Results](./BENCH.md) or run with `pnpm run bench:node` or `pnpm run bench:bun` yourself!
|
||||
|
||||
## License
|
||||
|
||||
MIT. Made with 💖
|
||||
|
||||
<!-- Badges -->
|
||||
|
||||
[npm-version-src]: https://img.shields.io/npm/v/destr?style=flat&colorA=18181B&colorB=F0DB4F
|
||||
[npm-version-href]: https://npmjs.com/package/destr
|
||||
[npm-downloads-src]: https://img.shields.io/npm/dm/destr?style=flat&colorA=18181B&colorB=F0DB4F
|
||||
[npm-downloads-href]: https://npmjs.com/package/destr
|
||||
[bundle-src]: https://img.shields.io/bundlephobia/minzip/destr?style=flat&colorA=18181B&colorB=F0DB4F
|
||||
[bundle-href]: https://bundlephobia.com/result?p=destr
|
||||
[license-src]: https://img.shields.io/github/license/unjs/destr.svg?style=flat&colorA=18181B&colorB=F0DB4F
|
||||
[license-href]: https://github.com/unjs/destr/blob/main/LICENSE
|
78
node_modules/destr/dist/index.cjs
generated
vendored
Normal file
78
node_modules/destr/dist/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/;
|
||||
const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
|
||||
const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
|
||||
function jsonParseTransform(key, value) {
|
||||
if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) {
|
||||
warnKeyDropped(key);
|
||||
return;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function warnKeyDropped(key) {
|
||||
console.warn(`[destr] Dropping "${key}" key to prevent prototype pollution.`);
|
||||
}
|
||||
function destr(value, options = {}) {
|
||||
if (typeof value !== "string") {
|
||||
return value;
|
||||
}
|
||||
if (value[0] === '"' && value[value.length - 1] === '"' && value.indexOf("\\") === -1) {
|
||||
return value.slice(1, -1);
|
||||
}
|
||||
const _value = value.trim();
|
||||
if (_value.length <= 9) {
|
||||
switch (_value.toLowerCase()) {
|
||||
case "true": {
|
||||
return true;
|
||||
}
|
||||
case "false": {
|
||||
return false;
|
||||
}
|
||||
case "undefined": {
|
||||
return void 0;
|
||||
}
|
||||
case "null": {
|
||||
return null;
|
||||
}
|
||||
case "nan": {
|
||||
return Number.NaN;
|
||||
}
|
||||
case "infinity": {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
case "-infinity": {
|
||||
return Number.NEGATIVE_INFINITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!JsonSigRx.test(value)) {
|
||||
if (options.strict) {
|
||||
throw new SyntaxError("[destr] Invalid JSON");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) {
|
||||
if (options.strict) {
|
||||
throw new Error("[destr] Possible prototype pollution");
|
||||
}
|
||||
return JSON.parse(value, jsonParseTransform);
|
||||
}
|
||||
return JSON.parse(value);
|
||||
} catch (error) {
|
||||
if (options.strict) {
|
||||
throw error;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
function safeDestr(value, options = {}) {
|
||||
return destr(value, { ...options, strict: true });
|
||||
}
|
||||
|
||||
exports.default = destr;
|
||||
exports.destr = destr;
|
||||
exports.safeDestr = safeDestr;
|
8
node_modules/destr/dist/index.d.cts
generated
vendored
Normal file
8
node_modules/destr/dist/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
type Options = {
|
||||
strict?: boolean;
|
||||
};
|
||||
declare function destr<T = unknown>(value: any, options?: Options): T;
|
||||
declare function safeDestr<T = unknown>(value: any, options?: Options): T;
|
||||
|
||||
export { destr as default, destr, safeDestr };
|
||||
export type { Options };
|
8
node_modules/destr/dist/index.d.mts
generated
vendored
Normal file
8
node_modules/destr/dist/index.d.mts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
type Options = {
|
||||
strict?: boolean;
|
||||
};
|
||||
declare function destr<T = unknown>(value: any, options?: Options): T;
|
||||
declare function safeDestr<T = unknown>(value: any, options?: Options): T;
|
||||
|
||||
export { destr as default, destr, safeDestr };
|
||||
export type { Options };
|
8
node_modules/destr/dist/index.d.ts
generated
vendored
Normal file
8
node_modules/destr/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
type Options = {
|
||||
strict?: boolean;
|
||||
};
|
||||
declare function destr<T = unknown>(value: any, options?: Options): T;
|
||||
declare function safeDestr<T = unknown>(value: any, options?: Options): T;
|
||||
|
||||
export { destr as default, destr, safeDestr };
|
||||
export type { Options };
|
72
node_modules/destr/dist/index.mjs
generated
vendored
Normal file
72
node_modules/destr/dist/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/;
|
||||
const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
|
||||
const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
|
||||
function jsonParseTransform(key, value) {
|
||||
if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) {
|
||||
warnKeyDropped(key);
|
||||
return;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function warnKeyDropped(key) {
|
||||
console.warn(`[destr] Dropping "${key}" key to prevent prototype pollution.`);
|
||||
}
|
||||
function destr(value, options = {}) {
|
||||
if (typeof value !== "string") {
|
||||
return value;
|
||||
}
|
||||
if (value[0] === '"' && value[value.length - 1] === '"' && value.indexOf("\\") === -1) {
|
||||
return value.slice(1, -1);
|
||||
}
|
||||
const _value = value.trim();
|
||||
if (_value.length <= 9) {
|
||||
switch (_value.toLowerCase()) {
|
||||
case "true": {
|
||||
return true;
|
||||
}
|
||||
case "false": {
|
||||
return false;
|
||||
}
|
||||
case "undefined": {
|
||||
return void 0;
|
||||
}
|
||||
case "null": {
|
||||
return null;
|
||||
}
|
||||
case "nan": {
|
||||
return Number.NaN;
|
||||
}
|
||||
case "infinity": {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
case "-infinity": {
|
||||
return Number.NEGATIVE_INFINITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!JsonSigRx.test(value)) {
|
||||
if (options.strict) {
|
||||
throw new SyntaxError("[destr] Invalid JSON");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) {
|
||||
if (options.strict) {
|
||||
throw new Error("[destr] Possible prototype pollution");
|
||||
}
|
||||
return JSON.parse(value, jsonParseTransform);
|
||||
}
|
||||
return JSON.parse(value);
|
||||
} catch (error) {
|
||||
if (options.strict) {
|
||||
throw error;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
function safeDestr(value, options = {}) {
|
||||
return destr(value, { ...options, strict: true });
|
||||
}
|
||||
|
||||
export { destr as default, destr, safeDestr };
|
7
node_modules/destr/lib/index.cjs
generated
vendored
Normal file
7
node_modules/destr/lib/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
const { destr, safeDestr } = require("../dist/index.cjs");
|
||||
|
||||
// Allow mixed default and named exports
|
||||
destr.destr = destr;
|
||||
destr.safeDestr = safeDestr;
|
||||
|
||||
module.exports = destr;
|
47
node_modules/destr/package.json
generated
vendored
Normal file
47
node_modules/destr/package.json
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "destr",
|
||||
"version": "2.0.5",
|
||||
"description": "A faster, secure and convenient alternative for JSON.parse",
|
||||
"repository": "unjs/destr",
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./lib/index.cjs"
|
||||
}
|
||||
},
|
||||
"main": "./lib/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"bench:bun": "pnpm build && bun --bun ./test/bench.mjs",
|
||||
"bench:node": "pnpm build && node ./test/bench.mjs",
|
||||
"build": "unbuild",
|
||||
"dev": "vitest dev",
|
||||
"lint": "eslint . && prettier -c src test",
|
||||
"lint:fix": "eslint . --fix && prettier -w src test",
|
||||
"release": "pnpm test && pnpm build && changelogen --release --push && npm publish",
|
||||
"test": "pnpm lint && vitest run --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hapi/bourne": "^3.0.0",
|
||||
"@vitest/coverage-v8": "^3.1.1",
|
||||
"changelogen": "^0.6.1",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-config-unjs": "^0.4.2",
|
||||
"mitata": "^1.0.34",
|
||||
"prettier": "^3.5.3",
|
||||
"secure-json-parse": "^4.0.0",
|
||||
"typescript": "^5.8.2",
|
||||
"unbuild": "~3.4",
|
||||
"vitest": "^3.1.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.7.1"
|
||||
}
|
Reference in New Issue
Block a user