fix: Add nixpacks configuration for Astro deployment

This commit is contained in:
Kunthawat Greethong
2026-03-02 12:35:14 +07:00
parent ede8e32591
commit 5a2fb71c40
10118 changed files with 1500179 additions and 24 deletions

110
dealplustech-astro/node_modules/devalue/src/base64.js generated vendored Normal file
View File

@@ -0,0 +1,110 @@
/**
* Base64 Encodes an arraybuffer
* @param {ArrayBuffer} arraybuffer
* @returns {string}
*/
export function encode64(arraybuffer) {
const dv = new DataView(arraybuffer);
let binaryString = "";
for (let i = 0; i < arraybuffer.byteLength; i++) {
binaryString += String.fromCharCode(dv.getUint8(i));
}
return binaryToAscii(binaryString);
}
/**
* Decodes a base64 string into an arraybuffer
* @param {string} string
* @returns {ArrayBuffer}
*/
export function decode64(string) {
const binaryString = asciiToBinary(string);
const arraybuffer = new ArrayBuffer(binaryString.length);
const dv = new DataView(arraybuffer);
for (let i = 0; i < arraybuffer.byteLength; i++) {
dv.setUint8(i, binaryString.charCodeAt(i));
}
return arraybuffer;
}
const KEY_STRING =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* Substitute for atob since it's deprecated in node.
* Does not do any input validation.
*
* @see https://github.com/jsdom/abab/blob/master/lib/atob.js
*
* @param {string} data
* @returns {string}
*/
function asciiToBinary(data) {
if (data.length % 4 === 0) {
data = data.replace(/==?$/, "");
}
let output = "";
let buffer = 0;
let accumulatedBits = 0;
for (let i = 0; i < data.length; i++) {
buffer <<= 6;
buffer |= KEY_STRING.indexOf(data[i]);
accumulatedBits += 6;
if (accumulatedBits === 24) {
output += String.fromCharCode((buffer & 0xff0000) >> 16);
output += String.fromCharCode((buffer & 0xff00) >> 8);
output += String.fromCharCode(buffer & 0xff);
buffer = accumulatedBits = 0;
}
}
if (accumulatedBits === 12) {
buffer >>= 4;
output += String.fromCharCode(buffer);
} else if (accumulatedBits === 18) {
buffer >>= 2;
output += String.fromCharCode((buffer & 0xff00) >> 8);
output += String.fromCharCode(buffer & 0xff);
}
return output;
}
/**
* Substitute for btoa since it's deprecated in node.
* Does not do any input validation.
*
* @see https://github.com/jsdom/abab/blob/master/lib/btoa.js
*
* @param {string} str
* @returns {string}
*/
function binaryToAscii(str) {
let out = "";
for (let i = 0; i < str.length; i += 3) {
/** @type {[number, number, number, number]} */
const groupsOfSix = [undefined, undefined, undefined, undefined];
groupsOfSix[0] = str.charCodeAt(i) >> 2;
groupsOfSix[1] = (str.charCodeAt(i) & 0x03) << 4;
if (str.length > i + 1) {
groupsOfSix[1] |= str.charCodeAt(i + 1) >> 4;
groupsOfSix[2] = (str.charCodeAt(i + 1) & 0x0f) << 2;
}
if (str.length > i + 2) {
groupsOfSix[2] |= str.charCodeAt(i + 2) >> 6;
groupsOfSix[3] = str.charCodeAt(i + 2) & 0x3f;
}
for (let j = 0; j < groupsOfSix.length; j++) {
if (typeof groupsOfSix[j] === "undefined") {
out += "=";
} else {
out += KEY_STRING[groupsOfSix[j]];
}
}
}
return out;
}

View File

@@ -0,0 +1,7 @@
export const UNDEFINED = -1;
export const HOLE = -2;
export const NAN = -3;
export const POSITIVE_INFINITY = -4;
export const NEGATIVE_INFINITY = -5;
export const NEGATIVE_ZERO = -6;
export const SPARSE = -7;

246
dealplustech-astro/node_modules/devalue/src/parse.js generated vendored Normal file
View File

@@ -0,0 +1,246 @@
import { decode64 } from './base64.js';
import {
HOLE,
NAN,
NEGATIVE_INFINITY,
NEGATIVE_ZERO,
POSITIVE_INFINITY,
SPARSE,
UNDEFINED
} from './constants.js';
/**
* Revive a value serialized with `devalue.stringify`
* @param {string} serialized
* @param {Record<string, (value: any) => any>} [revivers]
*/
export function parse(serialized, revivers) {
return unflatten(JSON.parse(serialized), revivers);
}
/**
* Revive a value flattened with `devalue.stringify`
* @param {number | any[]} parsed
* @param {Record<string, (value: any) => any>} [revivers]
*/
export function unflatten(parsed, revivers) {
if (typeof parsed === 'number') return hydrate(parsed, true);
if (!Array.isArray(parsed) || parsed.length === 0) {
throw new Error('Invalid input');
}
const values = /** @type {any[]} */ (parsed);
const hydrated = Array(values.length);
/**
* A set of values currently being hydrated with custom revivers,
* used to detect invalid cyclical dependencies
* @type {Set<number> | null}
*/
let hydrating = null;
/**
* @param {number} index
* @returns {any}
*/
function hydrate(index, standalone = false) {
if (index === UNDEFINED) return undefined;
if (index === NAN) return NaN;
if (index === POSITIVE_INFINITY) return Infinity;
if (index === NEGATIVE_INFINITY) return -Infinity;
if (index === NEGATIVE_ZERO) return -0;
if (standalone || typeof index !== 'number') {
throw new Error(`Invalid input`);
}
if (index in hydrated) return hydrated[index];
const value = values[index];
if (!value || typeof value !== 'object') {
hydrated[index] = value;
} else if (Array.isArray(value)) {
if (typeof value[0] === 'string') {
const type = value[0];
const reviver =
revivers && Object.hasOwn(revivers, type)
? revivers[type]
: undefined;
if (reviver) {
let i = value[1];
if (typeof i !== 'number') {
// if it's not a number, it was serialized by a builtin reviver
// so we need to munge it into the format expected by a custom reviver
i = values.push(value[1]) - 1;
}
hydrating ??= new Set();
if (hydrating.has(i)) {
throw new Error('Invalid circular reference');
}
hydrating.add(i);
hydrated[index] = reviver(hydrate(i));
hydrating.delete(i);
return hydrated[index];
}
switch (type) {
case 'Date':
hydrated[index] = new Date(value[1]);
break;
case 'Set':
const set = new Set();
hydrated[index] = set;
for (let i = 1; i < value.length; i += 1) {
set.add(hydrate(value[i]));
}
break;
case 'Map':
const map = new Map();
hydrated[index] = map;
for (let i = 1; i < value.length; i += 2) {
map.set(hydrate(value[i]), hydrate(value[i + 1]));
}
break;
case 'RegExp':
hydrated[index] = new RegExp(value[1], value[2]);
break;
case 'Object':
hydrated[index] = Object(value[1]);
break;
case 'BigInt':
hydrated[index] = BigInt(value[1]);
break;
case 'null':
const obj = Object.create(null);
hydrated[index] = obj;
for (let i = 1; i < value.length; i += 2) {
obj[value[i]] = hydrate(value[i + 1]);
}
break;
case 'Int8Array':
case 'Uint8Array':
case 'Uint8ClampedArray':
case 'Int16Array':
case 'Uint16Array':
case 'Int32Array':
case 'Uint32Array':
case 'Float32Array':
case 'Float64Array':
case 'BigInt64Array':
case 'BigUint64Array': {
if (values[value[1]][0] !== 'ArrayBuffer') {
// without this, if we receive malformed input we could
// end up trying to hydrate in a circle or allocate
// huge amounts of memory when we call `new TypedArrayConstructor(buffer)`
throw new Error('Invalid data');
}
const TypedArrayConstructor = globalThis[type];
const buffer = hydrate(value[1]);
const typedArray = new TypedArrayConstructor(buffer);
hydrated[index] =
value[2] !== undefined
? typedArray.subarray(value[2], value[3])
: typedArray;
break;
}
case 'ArrayBuffer': {
const base64 = value[1];
if (typeof base64 !== 'string') {
throw new Error('Invalid ArrayBuffer encoding');
}
const arraybuffer = decode64(base64);
hydrated[index] = arraybuffer;
break;
}
case 'Temporal.Duration':
case 'Temporal.Instant':
case 'Temporal.PlainDate':
case 'Temporal.PlainTime':
case 'Temporal.PlainDateTime':
case 'Temporal.PlainMonthDay':
case 'Temporal.PlainYearMonth':
case 'Temporal.ZonedDateTime': {
const temporalName = type.slice(9);
// @ts-expect-error TS doesn't know about Temporal yet
hydrated[index] = Temporal[temporalName].from(value[1]);
break;
}
case 'URL': {
const url = new URL(value[1]);
hydrated[index] = url;
break;
}
case 'URLSearchParams': {
const url = new URLSearchParams(value[1]);
hydrated[index] = url;
break;
}
default:
throw new Error(`Unknown type ${type}`);
}
} else if (value[0] === SPARSE) {
// Sparse array encoding: [SPARSE, length, idx, val, idx, val, ...]
const len = value[1];
const array = new Array(len);
hydrated[index] = array;
for (let i = 2; i < value.length; i += 2) {
const idx = value[i];
array[idx] = hydrate(value[i + 1]);
}
} else {
const array = new Array(value.length);
hydrated[index] = array;
for (let i = 0; i < value.length; i += 1) {
const n = value[i];
if (n === HOLE) continue;
array[i] = hydrate(n);
}
}
} else {
/** @type {Record<string, any>} */
const object = {};
hydrated[index] = object;
for (const key of Object.keys(value)) {
if (key === '__proto__') {
throw new Error('Cannot parse an object with a `__proto__` property');
}
const n = value[key];
object[key] = hydrate(n);
}
}
return hydrated[index];
}
return hydrate(0);
}

View File

@@ -0,0 +1,350 @@
import {
DevalueError,
enumerable_symbols,
get_type,
is_plain_object,
is_primitive,
stringify_key,
stringify_string,
valid_array_indices
} from './utils.js';
import {
HOLE,
NAN,
NEGATIVE_INFINITY,
NEGATIVE_ZERO,
POSITIVE_INFINITY,
SPARSE,
UNDEFINED
} from './constants.js';
import { encode64 } from './base64.js';
/**
* Turn a value into a JSON string that can be parsed with `devalue.parse`
* @param {any} value
* @param {Record<string, (value: any) => any>} [reducers]
*/
export function stringify(value, reducers) {
/** @type {any[]} */
const stringified = [];
/** @type {Map<any, number>} */
const indexes = new Map();
/** @type {Array<{ key: string, fn: (value: any) => any }>} */
const custom = [];
if (reducers) {
for (const key of Object.getOwnPropertyNames(reducers)) {
custom.push({ key, fn: reducers[key] });
}
}
/** @type {string[]} */
const keys = [];
let p = 0;
/** @param {any} thing */
function flatten(thing) {
if (thing === undefined) return UNDEFINED;
if (Number.isNaN(thing)) return NAN;
if (thing === Infinity) return POSITIVE_INFINITY;
if (thing === -Infinity) return NEGATIVE_INFINITY;
if (thing === 0 && 1 / thing < 0) return NEGATIVE_ZERO;
if (indexes.has(thing)) return indexes.get(thing);
const index = p++;
indexes.set(thing, index);
for (const { key, fn } of custom) {
const value = fn(thing);
if (value) {
stringified[index] = `["${key}",${flatten(value)}]`;
return index;
}
}
if (typeof thing === 'function') {
throw new DevalueError(`Cannot stringify a function`, keys, thing, value);
}
let str = '';
if (is_primitive(thing)) {
str = stringify_primitive(thing);
} else {
const type = get_type(thing);
switch (type) {
case 'Number':
case 'String':
case 'Boolean':
str = `["Object",${stringify_primitive(thing)}]`;
break;
case 'BigInt':
str = `["BigInt",${thing}]`;
break;
case 'Date':
const valid = !isNaN(thing.getDate());
str = `["Date","${valid ? thing.toISOString() : ''}"]`;
break;
case 'URL':
str = `["URL",${stringify_string(thing.toString())}]`;
break;
case 'URLSearchParams':
str = `["URLSearchParams",${stringify_string(thing.toString())}]`;
break;
case 'RegExp':
const { source, flags } = thing;
str = flags
? `["RegExp",${stringify_string(source)},"${flags}"]`
: `["RegExp",${stringify_string(source)}]`;
break;
case 'Array': {
// For dense arrays (no holes), we iterate normally.
// When we encounter the first hole, we call Object.keys
// to determine the sparseness, then decide between:
// - HOLE encoding: [-2, val, -2, ...] (default)
// - Sparse encoding: [-7, length, idx, val, ...] (for very sparse arrays)
// Only the sparse path avoids iterating every slot, which
// is what protects against the DoS of e.g. `arr[1000000] = 1`.
let mostly_dense = false;
str = '[';
for (let i = 0; i < thing.length; i += 1) {
if (i > 0) str += ',';
if (Object.hasOwn(thing, i)) {
keys.push(`[${i}]`);
str += flatten(thing[i]);
keys.pop();
} else if (mostly_dense) {
// Use dense encoding. The heuristic guarantees the
// array is only mildly sparse, so iterating over every
// slot is fine.
str += HOLE;
} else {
// Decide between HOLE encoding and sparse encoding.
//
// HOLE encoding: each hole is serialized as the HOLE
// sentinel (-2). For example, [, "a", ,] becomes
// [-2, 0, -2]. Each hole costs 3 chars ("-2" + comma).
//
// Sparse encoding: lists only populated indices.
// For example, [, "a", ,] becomes [-7, 3, 1, 0] — the
// -7 sentinel, the array length (3), then index-value
// pairs. This avoids paying per-hole, but each element
// costs extra chars to write its index.
//
// The values are the same size either way, so the
// choice comes down to structural overhead:
//
// HOLE overhead:
// 3 chars per hole ("-2" + comma)
// = (L - P) * 3
//
// Sparse overhead:
// "-7," — 3 chars (sparse sentinel + comma)
// + length + "," — (d + 1) chars (array length + comma)
// + per element: index + "," — (d + 1) chars
// = (4 + d) + P * (d + 1)
//
// where L is the array length, P is the number of
// populated elements, and d is the number of digits
// in L (an upper bound on the digits in any index).
//
// Sparse encoding is cheaper when:
// (4 + d) + P * (d + 1) < (L - P) * 3
const populated_keys = valid_array_indices(/** @type {any[]} */ (thing));
const population = populated_keys.length;
const d = String(thing.length).length;
const hole_cost = (thing.length - population) * 3;
const sparse_cost = 4 + d + population * (d + 1);
if (hole_cost > sparse_cost) {
str = '[' + SPARSE + ',' + thing.length;
for (let j = 0; j < populated_keys.length; j++) {
const key = populated_keys[j];
keys.push(`[${key}]`);
str += ',' + key + ',' + flatten(thing[key]);
keys.pop();
}
break;
} else {
mostly_dense = true;
str += HOLE;
}
}
}
str += ']';
break;
}
case 'Set':
str = '["Set"';
for (const value of thing) {
str += `,${flatten(value)}`;
}
str += ']';
break;
case 'Map':
str = '["Map"';
for (const [key, value] of thing) {
keys.push(
`.get(${is_primitive(key) ? stringify_primitive(key) : '...'})`
);
str += `,${flatten(key)},${flatten(value)}`;
keys.pop();
}
str += ']';
break;
case 'Int8Array':
case 'Uint8Array':
case 'Uint8ClampedArray':
case 'Int16Array':
case 'Uint16Array':
case 'Int32Array':
case 'Uint32Array':
case 'Float32Array':
case 'Float64Array':
case 'BigInt64Array':
case 'BigUint64Array': {
/** @type {import("./types.js").TypedArray} */
const typedArray = thing;
str = '["' + type + '",' + flatten(typedArray.buffer);
const a = thing.byteOffset;
const b = a + thing.byteLength;
// handle subarrays
if (a > 0 || b !== typedArray.buffer.byteLength) {
const m = +/(\d+)/.exec(type)[1] / 8;
str += `,${a / m},${b / m}`;
}
str += ']';
break;
}
case 'ArrayBuffer': {
/** @type {ArrayBuffer} */
const arraybuffer = thing;
const base64 = encode64(arraybuffer);
str = `["ArrayBuffer","${base64}"]`;
break;
}
case 'Temporal.Duration':
case 'Temporal.Instant':
case 'Temporal.PlainDate':
case 'Temporal.PlainTime':
case 'Temporal.PlainDateTime':
case 'Temporal.PlainMonthDay':
case 'Temporal.PlainYearMonth':
case 'Temporal.ZonedDateTime':
str = `["${type}",${stringify_string(thing.toString())}]`;
break;
default:
if (!is_plain_object(thing)) {
throw new DevalueError(
`Cannot stringify arbitrary non-POJOs`,
keys,
thing,
value
);
}
if (enumerable_symbols(thing).length > 0) {
throw new DevalueError(
`Cannot stringify POJOs with symbolic keys`,
keys,
thing,
value
);
}
if (Object.getPrototypeOf(thing) === null) {
str = '["null"';
for (const key of Object.keys(thing)) {
if (key === '__proto__') {
throw new DevalueError(
`Cannot stringify objects with __proto__ keys`,
keys,
thing,
value
);
}
keys.push(stringify_key(key));
str += `,${stringify_string(key)},${flatten(thing[key])}`;
keys.pop();
}
str += ']';
} else {
str = '{';
let started = false;
for (const key of Object.keys(thing)) {
if (key === '__proto__') {
throw new DevalueError(
`Cannot stringify objects with __proto__ keys`,
keys,
thing,
value
);
}
if (started) str += ',';
started = true;
keys.push(stringify_key(key));
str += `${stringify_string(key)}:${flatten(thing[key])}`;
keys.pop();
}
str += '}';
}
}
}
stringified[index] = str;
return index;
}
const index = flatten(value);
// special case — value is represented as a negative index
if (index < 0) return `${index}`;
return `[${stringified.join(',')}]`;
}
/**
* @param {any} thing
* @returns {string}
*/
function stringify_primitive(thing) {
const type = typeof thing;
if (type === 'string') return stringify_string(thing);
if (thing instanceof String) return stringify_string(thing.toString());
if (thing === void 0) return UNDEFINED.toString();
if (thing === 0 && 1 / thing < 0) return NEGATIVE_ZERO.toString();
if (type === 'bigint') return `["BigInt","${thing}"]`;
return String(thing);
}

View File

@@ -0,0 +1 @@
export type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;

490
dealplustech-astro/node_modules/devalue/src/uneval.js generated vendored Normal file
View File

@@ -0,0 +1,490 @@
import {
DevalueError,
enumerable_symbols,
escaped,
get_type,
is_plain_object,
is_primitive,
stringify_key,
stringify_string,
valid_array_indices
} from './utils.js';
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
const unsafe_chars = /[<\b\f\n\r\t\0\u2028\u2029]/g;
const reserved =
/^(?:do|if|in|for|int|let|new|try|var|byte|case|char|else|enum|goto|long|this|void|with|await|break|catch|class|const|final|float|short|super|throw|while|yield|delete|double|export|import|native|return|switch|throws|typeof|boolean|default|extends|finally|package|private|abstract|continue|debugger|function|volatile|interface|protected|transient|implements|instanceof|synchronized)$/;
/**
* Turn a value into the JavaScript that creates an equivalent value
* @param {any} value
* @param {(value: any, uneval: (value: any) => string) => string | void} [replacer]
*/
export function uneval(value, replacer) {
const counts = new Map();
/** @type {string[]} */
const keys = [];
const custom = new Map();
/** @param {any} thing */
function walk(thing) {
if (!is_primitive(thing)) {
if (counts.has(thing)) {
counts.set(thing, counts.get(thing) + 1);
return;
}
counts.set(thing, 1);
if (replacer) {
const str = replacer(thing, (value) => uneval(value, replacer));
if (typeof str === 'string') {
custom.set(thing, str);
return;
}
}
if (typeof thing === 'function') {
throw new DevalueError(`Cannot stringify a function`, keys, thing, value);
}
const type = get_type(thing);
switch (type) {
case 'Number':
case 'BigInt':
case 'String':
case 'Boolean':
case 'Date':
case 'RegExp':
case 'URL':
case 'URLSearchParams':
return;
case 'Array':
/** @type {any[]} */ (thing).forEach((value, i) => {
keys.push(`[${i}]`);
walk(value);
keys.pop();
});
break;
case 'Set':
Array.from(thing).forEach(walk);
break;
case 'Map':
for (const [key, value] of thing) {
keys.push(
`.get(${is_primitive(key) ? stringify_primitive(key) : '...'})`
);
walk(value);
keys.pop();
}
break;
case 'Int8Array':
case 'Uint8Array':
case 'Uint8ClampedArray':
case 'Int16Array':
case 'Uint16Array':
case 'Int32Array':
case 'Uint32Array':
case 'Float32Array':
case 'Float64Array':
case 'BigInt64Array':
case 'BigUint64Array':
walk(thing.buffer);
return;
case 'ArrayBuffer':
return;
case 'Temporal.Duration':
case 'Temporal.Instant':
case 'Temporal.PlainDate':
case 'Temporal.PlainTime':
case 'Temporal.PlainDateTime':
case 'Temporal.PlainMonthDay':
case 'Temporal.PlainYearMonth':
case 'Temporal.ZonedDateTime':
return;
default:
if (!is_plain_object(thing)) {
throw new DevalueError(
`Cannot stringify arbitrary non-POJOs`,
keys,
thing,
value
);
}
if (enumerable_symbols(thing).length > 0) {
throw new DevalueError(
`Cannot stringify POJOs with symbolic keys`,
keys,
thing,
value
);
}
for (const key of Object.keys(thing)) {
if (key === '__proto__') {
throw new DevalueError(
`Cannot stringify objects with __proto__ keys`,
keys,
thing,
value
);
}
keys.push(stringify_key(key));
walk(thing[key]);
keys.pop();
}
}
}
}
walk(value);
const names = new Map();
Array.from(counts)
.filter((entry) => entry[1] > 1)
.sort((a, b) => b[1] - a[1])
.forEach((entry, i) => {
names.set(entry[0], get_name(i));
});
/**
* @param {any} thing
* @returns {string}
*/
function stringify(thing) {
if (names.has(thing)) {
return names.get(thing);
}
if (is_primitive(thing)) {
return stringify_primitive(thing);
}
if (custom.has(thing)) {
return custom.get(thing);
}
const type = get_type(thing);
switch (type) {
case 'Number':
case 'String':
case 'Boolean':
return `Object(${stringify(thing.valueOf())})`;
case 'RegExp':
return `new RegExp(${stringify_string(thing.source)}, "${
thing.flags
}")`;
case 'Date':
return `new Date(${thing.getTime()})`;
case 'URL':
return `new URL(${stringify_string(thing.toString())})`;
case 'URLSearchParams':
return `new URLSearchParams(${stringify_string(thing.toString())})`;
case 'Array': {
// For dense arrays (no holes), we iterate normally.
// When we encounter the first hole, we call Object.keys
// to determine the sparseness, then decide between:
// - Array literal with holes: [,"a",,] (default)
// - Object.assign: Object.assign(Array(n),{...}) (for very sparse arrays)
// Only the Object.assign path avoids iterating every slot, which
// is what protects against the DoS of e.g. `arr[1000000] = 1`.
let has_holes = false;
let result = '[';
for (let i = 0; i < thing.length; i += 1) {
if (i > 0) result += ',';
if (Object.hasOwn(thing, i)) {
result += stringify(thing[i]);
} else if (!has_holes) {
// Decide between array literal and Object.assign.
//
// Array literal: holes are consecutive commas.
// For example, [, "a", ,] is written as [,"a",,].
// Each hole costs 1 char (a comma).
//
// Object.assign: populated indices are listed explicitly.
// For example, [, "a", ,] would be written as
// Object.assign(Array(3),{1:"a"}). This avoids paying
// per-hole, but has a large fixed overhead for the
// "Object.assign(Array(n),{...})" wrapper, and each
// element costs extra chars for its index and colon.
//
// The serialized values are the same size either way, so
// the choice comes down to the structural overhead:
//
// Array literal overhead:
// 1 char per element or hole (comma separators)
// + 2 chars for "[" and "]"
// = L + 2
//
// Object.assign overhead:
// "Object.assign(Array(" — 20 chars
// + length — d chars
// + "),{" — 3 chars
// + for each populated element:
// index + ":" + "," — (d + 2) chars
// + "})" — 2 chars
// = (25 + d) + P * (d + 2)
//
// where L is the array length, P is the number of
// populated elements, and d is the number of digits
// in L (an upper bound on the digits in any index).
//
// Object.assign is cheaper when:
// (25 + d) + P * (d + 2) < L + 2
const populated_keys = valid_array_indices(/** @type {any[]} */ (thing));
const population = populated_keys.length;
const d = String(thing.length).length;
const hole_cost = thing.length + 2;
const sparse_cost = (25 + d) + population * (d + 2);
if (hole_cost > sparse_cost) {
const entries = populated_keys
.map((k) => `${k}:${stringify(thing[k])}`)
.join(',');
return `Object.assign(Array(${thing.length}),{${entries}})`;
}
// Re-process this index as a hole in the array literal
has_holes = true;
i -= 1;
}
// else: already decided on array literal, hole is just an empty slot
// (the comma separator is all we need — no content for this position)
}
const tail = thing.length === 0 || thing.length - 1 in thing ? '' : ',';
return result + tail + ']';
}
case 'Set':
case 'Map':
return `new ${type}([${Array.from(thing).map(stringify).join(',')}])`;
case 'Int8Array':
case 'Uint8Array':
case 'Uint8ClampedArray':
case 'Int16Array':
case 'Uint16Array':
case 'Int32Array':
case 'Uint32Array':
case 'Float32Array':
case 'Float64Array':
case 'BigInt64Array':
case 'BigUint64Array': {
let str = `new ${type}`;
if (counts.get(thing.buffer) === 1) {
const array = new thing.constructor(thing.buffer);
str += `([${array}])`;
} else {
str += `([${stringify(thing.buffer)}])`;
}
const a = thing.byteOffset;
const b = a + thing.byteLength;
// handle subarrays
if (a > 0 || b !== thing.buffer.byteLength) {
const m = +/(\d+)/.exec(type)[1] / 8;
str += `.subarray(${a / m},${b / m})`;
}
return str;
}
case 'ArrayBuffer': {
const ui8 = new Uint8Array(thing);
return `new Uint8Array([${ui8.toString()}]).buffer`;
}
case 'Temporal.Duration':
case 'Temporal.Instant':
case 'Temporal.PlainDate':
case 'Temporal.PlainTime':
case 'Temporal.PlainDateTime':
case 'Temporal.PlainMonthDay':
case 'Temporal.PlainYearMonth':
case 'Temporal.ZonedDateTime':
return `${type}.from(${stringify_string(thing.toString())})`;
default:
const keys = Object.keys(thing);
const obj = keys
.map((key) => `${safe_key(key)}:${stringify(thing[key])}`)
.join(',');
const proto = Object.getPrototypeOf(thing);
if (proto === null) {
return keys.length > 0
? `{${obj},__proto__:null}`
: `{__proto__:null}`;
}
return `{${obj}}`;
}
}
const str = stringify(value);
if (names.size) {
/** @type {string[]} */
const params = [];
/** @type {string[]} */
const statements = [];
/** @type {string[]} */
const values = [];
names.forEach((name, thing) => {
params.push(name);
if (custom.has(thing)) {
values.push(/** @type {string} */ (custom.get(thing)));
return;
}
if (is_primitive(thing)) {
values.push(stringify_primitive(thing));
return;
}
const type = get_type(thing);
switch (type) {
case 'Number':
case 'String':
case 'Boolean':
values.push(`Object(${stringify(thing.valueOf())})`);
break;
case 'RegExp':
values.push(thing.toString());
break;
case 'Date':
values.push(`new Date(${thing.getTime()})`);
break;
case 'Array':
values.push(`Array(${thing.length})`);
/** @type {any[]} */ (thing).forEach((v, i) => {
statements.push(`${name}[${i}]=${stringify(v)}`);
});
break;
case 'Set':
values.push(`new Set`);
statements.push(
`${name}.${Array.from(thing)
.map((v) => `add(${stringify(v)})`)
.join('.')}`
);
break;
case 'Map':
values.push(`new Map`);
statements.push(
`${name}.${Array.from(thing)
.map(([k, v]) => `set(${stringify(k)}, ${stringify(v)})`)
.join('.')}`
);
break;
case 'ArrayBuffer':
values.push(
`new Uint8Array([${new Uint8Array(thing).join(',')}]).buffer`
);
break;
default:
values.push(
Object.getPrototypeOf(thing) === null ? 'Object.create(null)' : '{}'
);
Object.keys(thing).forEach((key) => {
statements.push(
`${name}${safe_prop(key)}=${stringify(thing[key])}`
);
});
}
});
statements.push(`return ${str}`);
return `(function(${params.join(',')}){${statements.join(
';'
)}}(${values.join(',')}))`;
} else {
return str;
}
}
/** @param {number} num */
function get_name(num) {
let name = '';
do {
name = chars[num % chars.length] + name;
num = ~~(num / chars.length) - 1;
} while (num >= 0);
return reserved.test(name) ? `${name}0` : name;
}
/** @param {string} c */
function escape_unsafe_char(c) {
return escaped[c] || c;
}
/** @param {string} str */
function escape_unsafe_chars(str) {
return str.replace(unsafe_chars, escape_unsafe_char);
}
/** @param {string} key */
function safe_key(key) {
return /^[_$a-zA-Z][_$a-zA-Z0-9]*$/.test(key)
? key
: escape_unsafe_chars(JSON.stringify(key));
}
/** @param {string} key */
function safe_prop(key) {
return /^[_$a-zA-Z][_$a-zA-Z0-9]*$/.test(key)
? `.${key}`
: `[${escape_unsafe_chars(JSON.stringify(key))}]`;
}
/** @param {any} thing */
function stringify_primitive(thing) {
if (typeof thing === 'string') return stringify_string(thing);
if (thing === void 0) return 'void 0';
if (thing === 0 && 1 / thing < 0) return '-0';
const str = String(thing);
if (typeof thing === 'number') return str.replace(/^(-)?0\./, '$1.');
if (typeof thing === 'bigint') return thing + 'n';
return str;
}

148
dealplustech-astro/node_modules/devalue/src/utils.js generated vendored Normal file
View File

@@ -0,0 +1,148 @@
/** @type {Record<string, string>} */
export const escaped = {
'<': '\\u003C',
'\\': '\\\\',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\u2028': '\\u2028',
'\u2029': '\\u2029'
};
export class DevalueError extends Error {
/**
* @param {string} message
* @param {string[]} keys
* @param {any} [value] - The value that failed to be serialized
* @param {any} [root] - The root value being serialized
*/
constructor(message, keys, value, root) {
super(message);
this.name = 'DevalueError';
this.path = keys.join('');
this.value = value;
this.root = root;
}
}
/** @param {any} thing */
export function is_primitive(thing) {
return Object(thing) !== thing;
}
const object_proto_names = /* @__PURE__ */ Object.getOwnPropertyNames(
Object.prototype
)
.sort()
.join('\0');
/** @param {any} thing */
export function is_plain_object(thing) {
const proto = Object.getPrototypeOf(thing);
return (
proto === Object.prototype ||
proto === null ||
Object.getPrototypeOf(proto) === null ||
Object.getOwnPropertyNames(proto).sort().join('\0') === object_proto_names
);
}
/** @param {any} thing */
export function get_type(thing) {
return Object.prototype.toString.call(thing).slice(8, -1);
}
/** @param {string} char */
function get_escaped_char(char) {
switch (char) {
case '"':
return '\\"';
case '<':
return '\\u003C';
case '\\':
return '\\\\';
case '\n':
return '\\n';
case '\r':
return '\\r';
case '\t':
return '\\t';
case '\b':
return '\\b';
case '\f':
return '\\f';
case '\u2028':
return '\\u2028';
case '\u2029':
return '\\u2029';
default:
return char < ' '
? `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`
: '';
}
}
/** @param {string} str */
export function stringify_string(str) {
let result = '';
let last_pos = 0;
const len = str.length;
for (let i = 0; i < len; i += 1) {
const char = str[i];
const replacement = get_escaped_char(char);
if (replacement) {
result += str.slice(last_pos, i) + replacement;
last_pos = i + 1;
}
}
return `"${last_pos === 0 ? str : result + str.slice(last_pos)}"`;
}
/** @param {Record<string | symbol, any>} object */
export function enumerable_symbols(object) {
return Object.getOwnPropertySymbols(object).filter(
(symbol) => Object.getOwnPropertyDescriptor(object, symbol).enumerable
);
}
const is_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
/** @param {string} key */
export function stringify_key(key) {
return is_identifier.test(key) ? '.' + key : '[' + JSON.stringify(key) + ']';
}
/** @param {string} s */
function is_valid_array_index(s) {
if (s.length === 0) return false;
if (s.length > 1 && s.charCodeAt(0) === 48) return false; // leading zero
for (let i = 0; i < s.length; i++) {
const c = s.charCodeAt(i);
if (c < 48 || c > 57) return false;
}
// by this point we know it's a string of digits, but it has to be within the range of valid array indices
const n = +s;
if (n >= 2 ** 32 - 1) return false;
if (n < 0) return false;
return true;
}
/**
* Finds the populated indices of an array.
* @param {unknown[]} array
*/
export function valid_array_indices(array) {
const keys = Object.keys(array);
for (var i = keys.length - 1; i >= 0; i--) {
if (is_valid_array_index(keys[i])) {
break;
}
}
keys.length = i + 1;
return keys;
}

View File

@@ -0,0 +1,63 @@
import * as assert from 'uvu/assert';
import { suite } from 'uvu';
import { valid_array_indices } from './utils.js';
const test = suite('valid_array_indices');
test('returns all indices for a normal dense array', () => {
const arr = ['a', 'b', 'c'];
assert.equal(valid_array_indices(arr), ['0', '1', '2']);
});
test('returns empty array for an empty array', () => {
assert.equal(valid_array_indices([]), []);
});
test('returns populated indices for a sparse array', () => {
const arr = [, 'b', ,];
assert.equal(valid_array_indices(arr), ['1']);
});
test('strips non-numeric properties from a dense array', () => {
const arr = ['a', 'b'];
arr.foo = 'x';
arr.bar = 42;
assert.equal(valid_array_indices(arr), ['0', '1']);
});
test('strips non-numeric properties from a very sparse array', () => {
const arr = [];
arr[1_000_000] = 'x';
arr.foo = 'should be ignored';
assert.equal(valid_array_indices(arr), ['1000000']);
});
test('returns empty array when only non-numeric properties exist', () => {
const arr = [];
arr.foo = 'x';
arr.bar = 42;
assert.equal(valid_array_indices(arr), []);
});
test('handles multiple non-numeric properties after indices', () => {
const arr = [1, 2, 3];
arr.a = 'x';
arr.b = 'y';
arr.c = 'z';
assert.equal(valid_array_indices(arr), ['0', '1', '2']);
});
test('handles a single-element array with non-numeric property', () => {
const arr = ['only'];
arr.extra = true;
assert.equal(valid_array_indices(arr), ['0']);
});
test('handles array properties pretending to be indices', () => {
const arr = ['a', 'b'];
arr[-1] = 'negative index';
arr[2**32 - 1] = 'too large index';
assert.equal(valid_array_indices(arr), ['0', '1']);
})
test.run();