superjs-core 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/io/index.ts"],"sourcesContent":["/**\n * Options for CSV parsing.\n */\nexport interface CsvOptions {\n delimiter?: string\n header?: boolean\n skipEmptyLines?: boolean\n}\n\n/**\n * Parses a CSV string into an array of records (objects).\n *\n * @param input - CSV string\n * @param options - Optional parsing options\n */\nexport function parseCsv(input: string, options?: CsvOptions): Record<string, string>[] {\n const { delimiter = ',', header = true, skipEmptyLines = true } = options ?? {}\n\n const lines = input.split(/\\r?\\n/)\n const rows: string[][] = []\n\n for (const line of lines) {\n const trimmed = line.trim()\n if (skipEmptyLines && trimmed.length === 0) continue\n const values = parseCsvLine(trimmed, delimiter)\n rows.push(values)\n }\n\n if (rows.length === 0) return []\n\n if (header) {\n const [head, ...body] = rows\n if (head === undefined) return []\n return body.map(row => {\n const record: Record<string, string> = {}\n for (let i = 0; i < head.length; i++) {\n record[head[i]!] = row[i] ?? ''\n }\n return record\n })\n }\n\n return rows.map(row => {\n const record: Record<string, string> = {}\n for (let i = 0; i < row.length; i++) {\n record[String(i)] = row[i]!\n }\n return record\n })\n}\n\nfunction parseCsvLine(line: string, delimiter: string): string[] {\n const result: string[] = []\n let current = ''\n let inQuotes = false\n\n for (let i = 0; i < line.length; i++) {\n const ch = line[i]!\n if (inQuotes) {\n if (ch === '\"') {\n if (line[i + 1] === '\"') {\n current += '\"'\n i++\n } else {\n inQuotes = false\n }\n } else {\n current += ch\n }\n } else {\n if (ch === '\"') {\n inQuotes = true\n } else if (ch === delimiter) {\n result.push(current)\n current = ''\n } else {\n current += ch\n }\n }\n }\n result.push(current)\n return result\n}\n\n/**\n * Converts an array of records to a CSV string.\n */\nexport function stringifyCsv(data: Record<string, unknown>[], options?: { delimiter?: string }): string {\n const { delimiter = ',' } = options ?? {}\n if (data.length === 0) return ''\n\n const headers = Object.keys(data[0]!)\n const lines: string[] = [headers.map(v => escapeCsvField(v, delimiter)).join(delimiter)]\n\n for (const record of data) {\n const row = headers.map(h => escapeCsvField(String(record[h] ?? ''), delimiter))\n lines.push(row.join(delimiter))\n }\n\n return lines.join('\\n')\n}\n\nfunction escapeCsvField(value: string, delimiter: string): string {\n if (value.includes('\"') || value.includes(delimiter) || value.includes('\\n') || value.includes('\\r')) {\n return '\"' + value.replace(/\"/g, '\"\"') + '\"'\n }\n return value\n}\n\n/**\n * Safely parses a JSON string, returning the default value or null on failure.\n */\nexport function safeJsonParse<T>(input: string, default_?: T): T | null {\n try {\n return JSON.parse(input) as T\n } catch {\n return default_ ?? null\n }\n}\n\n/**\n * Reads an environment variable with optional default.\n */\nexport function env(name: string, default_?: string): string {\n const value = process.env[name]\n return value ?? default_ ?? ''\n}\n\n/**\n * Reads an environment variable as an integer.\n */\nexport function envInt(name: string, default_?: number): number {\n const value = process.env[name]\n if (value === undefined || value === '') return default_ ?? 0\n const parsed = Number.parseInt(value, 10)\n return Number.isNaN(parsed) ? (default_ ?? 0) : parsed\n}\n\n/**\n * Reads an environment variable as a boolean.\n */\nexport function envBool(name: string, default_?: boolean): boolean {\n const value = process.env[name]\n if (value === undefined || value === '') return default_ ?? false\n return value === 'true' || value === '1' || value === 'yes'\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/io/index.ts"],"sourcesContent":["/**\r\n * Options for CSV parsing.\r\n */\r\nexport interface CsvOptions {\r\n delimiter?: string\r\n header?: boolean\r\n skipEmptyLines?: boolean\r\n}\r\n\r\n/**\r\n * Parses a CSV string into an array of records (objects).\r\n *\r\n * @param input - CSV string\r\n * @param options - Optional parsing options\r\n */\r\nexport function parseCsv(input: string, options?: CsvOptions): Record<string, string>[] {\r\n const { delimiter = ',', header = true, skipEmptyLines = true } = options ?? {}\r\n\r\n const lines = input.split(/\\r?\\n/)\r\n const rows: string[][] = []\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim()\r\n if (skipEmptyLines && trimmed.length === 0) continue\r\n const values = parseCsvLine(trimmed, delimiter)\r\n rows.push(values)\r\n }\r\n\r\n if (rows.length === 0) return []\r\n\r\n if (header) {\r\n const [head, ...body] = rows\r\n if (head === undefined) return []\r\n return body.map(row => {\r\n const record: Record<string, string> = {}\r\n for (let i = 0; i < head.length; i++) {\r\n record[head[i]!] = row[i] ?? ''\r\n }\r\n return record\r\n })\r\n }\r\n\r\n return rows.map(row => {\r\n const record: Record<string, string> = {}\r\n for (let i = 0; i < row.length; i++) {\r\n record[String(i)] = row[i]!\r\n }\r\n return record\r\n })\r\n}\r\n\r\nfunction parseCsvLine(line: string, delimiter: string): string[] {\r\n const result: string[] = []\r\n let current = ''\r\n let inQuotes = false\r\n\r\n for (let i = 0; i < line.length; i++) {\r\n const ch = line[i]!\r\n if (inQuotes) {\r\n if (ch === '\"') {\r\n if (line[i + 1] === '\"') {\r\n current += '\"'\r\n i++\r\n } else {\r\n inQuotes = false\r\n }\r\n } else {\r\n current += ch\r\n }\r\n } else {\r\n if (ch === '\"') {\r\n inQuotes = true\r\n } else if (ch === delimiter) {\r\n result.push(current)\r\n current = ''\r\n } else {\r\n current += ch\r\n }\r\n }\r\n }\r\n result.push(current)\r\n return result\r\n}\r\n\r\n/**\r\n * Converts an array of records to a CSV string.\r\n */\r\nexport function stringifyCsv(data: Record<string, unknown>[], options?: { delimiter?: string }): string {\r\n const { delimiter = ',' } = options ?? {}\r\n if (data.length === 0) return ''\r\n\r\n const headers = Object.keys(data[0]!)\r\n const lines: string[] = [headers.map(v => escapeCsvField(v, delimiter)).join(delimiter)]\r\n\r\n for (const record of data) {\r\n const row = headers.map(h => escapeCsvField(String(record[h] ?? ''), delimiter))\r\n lines.push(row.join(delimiter))\r\n }\r\n\r\n return lines.join('\\n')\r\n}\r\n\r\nfunction escapeCsvField(value: string, delimiter: string): string {\r\n if (value.includes('\"') || value.includes(delimiter) || value.includes('\\n') || value.includes('\\r')) {\r\n return '\"' + value.replace(/\"/g, '\"\"') + '\"'\r\n }\r\n return value\r\n}\r\n\r\n/**\r\n * Safely parses a JSON string, returning the default value or null on failure.\r\n */\r\nexport function safeJsonParse<T>(input: string, default_?: T): T | null {\r\n try {\r\n return JSON.parse(input) as T\r\n } catch {\r\n return default_ ?? null\r\n }\r\n}\r\n\r\n/**\r\n * Reads an environment variable with optional default.\r\n */\r\nexport function env(name: string, default_?: string): string {\r\n const value = process.env[name]\r\n return value ?? default_ ?? ''\r\n}\r\n\r\n/**\r\n * Reads an environment variable as an integer.\r\n */\r\nexport function envInt(name: string, default_?: number): number {\r\n const value = process.env[name]\r\n if (value === undefined || value === '') return default_ ?? 0\r\n const parsed = Number.parseInt(value, 10)\r\n return Number.isNaN(parsed) ? (default_ ?? 0) : parsed\r\n}\r\n\r\n/**\r\n * Reads an environment variable as a boolean.\r\n */\r\nexport function envBool(name: string, default_?: boolean): boolean {\r\n const value = process.env[name]\r\n if (value === undefined || value === '') return default_ ?? false\r\n return value === 'true' || value === '1' || value === 'yes'\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/math/index.ts"],"sourcesContent":["/**\n * Error thrown when attempting to divide by zero.\n */\nexport class DivisionByZeroError extends Error {\n constructor() {\n super('Division by zero')\n this.name = 'DivisionByZeroError'\n }\n}\n\nfunction getPrecision(value: number): number {\n if (!isFinite(value)) return 0\n const eIndex = String(value).indexOf('e')\n if (eIndex > -1) {\n const exp = parseInt(String(value).slice(eIndex + 1), 10)\n if (exp < 0) return Math.abs(exp)\n return 0\n }\n const str = String(value)\n const dot = str.indexOf('.')\n return dot === -1 ? 0 : str.length - dot - 1\n}\n\nfunction toPrecisionFactor(a: number, b: number): number {\n return Math.pow(10, Math.max(getPrecision(a), getPrecision(b)))\n}\n\n/**\n * Safely adds two numbers, handling floating-point precision.\n *\n * @param a - First number.\n * @param b - Second number.\n * @returns The sum.\n */\nexport function add(a: number, b: number): number {\n const factor = toPrecisionFactor(a, b)\n return (Math.round(a * factor) + Math.round(b * factor)) / factor\n}\n\n/**\n * Safely subtracts two numbers, handling floating-point precision.\n *\n * @param a - First number.\n * @param b - Second number.\n * @returns The difference.\n */\nexport function sub(a: number, b: number): number {\n const factor = toPrecisionFactor(a, b)\n return (Math.round(a * factor) - Math.round(b * factor)) / factor\n}\n\n/**\n * Safely multiplies two numbers, handling floating-point precision.\n *\n * @param a - First number.\n * @param b - Second number.\n * @returns The product.\n */\nexport function mul(a: number, b: number): number {\n const factorA = toPrecisionFactor(a, 1)\n const factorB = toPrecisionFactor(1, b)\n const result = (Math.round(a * factorA) * Math.round(b * factorB)) / (factorA * factorB)\n return result\n}\n\n/**\n * Safely divides two numbers.\n *\n * @param a - The dividend.\n * @param b - The divisor.\n * @returns The quotient.\n * @throws {DivisionByZeroError} If `b` is zero.\n */\nexport function div(a: number, b: number): number {\n if (b === 0) throw new DivisionByZeroError()\n const factor = toPrecisionFactor(a, b)\n return Math.round(a * factor) / Math.round(b * factor)\n}\n\n/**\n * Rounds a number to the given precision.\n *\n * @param value - The number to round.\n * @param precision - Number of decimal places (default 0).\n * @returns The rounded value.\n */\nexport function round(value: number, precision: number = 0): number {\n const factor = Math.pow(10, precision)\n return Math.round(value * factor) / factor\n}\n\n/**\n * Floors a number to the given precision.\n *\n * @param value - The number to floor.\n * @param precision - Number of decimal places (default 0).\n * @returns The floored value.\n */\nexport function floor(value: number, precision: number = 0): number {\n const factor = Math.pow(10, precision)\n return Math.floor(value * factor) / factor\n}\n\n/**\n * Ceils a number to the given precision.\n *\n * @param value - The number to ceil.\n * @param precision - Number of decimal places (default 0).\n * @returns The ceiled value.\n */\nexport function ceil(value: number, precision: number = 0): number {\n const factor = Math.pow(10, precision)\n return Math.ceil(value * factor) / factor\n}\n\n/**\n * Checks if two numbers are approximately equal within a tolerance.\n *\n * @param a - First number.\n * @param b - Second number.\n * @param tolerance - Maximum difference (default `Number.EPSILON`).\n * @returns Whether the numbers are approximately equal.\n */\nexport function approxEqual(a: number, b: number, tolerance: number = Number.EPSILON): boolean {\n return Math.abs(a - b) <= tolerance\n}\n\n/**\n * Clamps a value within the inclusive range [min, max].\n *\n * @param value - The value to clamp.\n * @param min - The lower bound.\n * @param max - The upper bound.\n * @returns The clamped value.\n * @throws {RangeError} If `min` exceeds `max`.\n */\nexport function clamp(value: number, min: number, max: number): number {\n if (min > max) {\n throw new RangeError('Minimum value cannot exceed maximum value')\n }\n return Math.min(Math.max(value, min), max)\n}\n\n/**\n * Computes the sum of an array of numbers.\n *\n * @param values - Array of numbers.\n * @returns The total sum.\n */\nexport function sum(values: number[]): number {\n let total = 0\n for (let i = 0; i < values.length; i++) {\n total += values[i]!\n }\n return total\n}\n\n/**\n * Computes the average (mean) of an array of numbers.\n *\n * @param values - Array of numbers.\n * @returns The average.\n * @throws {RangeError} If the array is empty.\n */\nexport function average(values: number[]): number {\n if (values.length === 0) {\n throw new RangeError('Cannot compute average of an empty array')\n }\n return sum(values) / values.length\n}\n\n/**\n * Generates a random integer between `min` and `max` (inclusive).\n *\n * @param min - The minimum integer.\n * @param max - The maximum integer.\n * @returns A random integer.\n * @throws {RangeError} If arguments are not integers or `min > max`.\n */\nexport function randomInt(min: number, max: number): number {\n if (!Number.isInteger(min) || !Number.isInteger(max)) {\n throw new RangeError('Arguments must be integers')\n }\n if (min > max) {\n throw new RangeError('Minimum value cannot exceed maximum value')\n }\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\n/**\n * Checks if a number is within the inclusive range [min, max].\n *\n * @param value - The number to check.\n * @param min - The lower bound.\n * @param max - The upper bound.\n * @returns Whether the value is in range.\n */\nexport function inRange(value: number, min: number, max: number): boolean {\n return value >= min && value <= max\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/math/index.ts"],"sourcesContent":["/**\r\n * Error thrown when attempting to divide by zero.\r\n */\r\nexport class DivisionByZeroError extends Error {\r\n constructor() {\r\n super('Division by zero')\r\n this.name = 'DivisionByZeroError'\r\n }\r\n}\r\n\r\nfunction getPrecision(value: number): number {\r\n if (!isFinite(value)) return 0\r\n const eIndex = String(value).indexOf('e')\r\n if (eIndex > -1) {\r\n const exp = parseInt(String(value).slice(eIndex + 1), 10)\r\n if (exp < 0) return Math.abs(exp)\r\n return 0\r\n }\r\n const str = String(value)\r\n const dot = str.indexOf('.')\r\n return dot === -1 ? 0 : str.length - dot - 1\r\n}\r\n\r\nfunction toPrecisionFactor(a: number, b: number): number {\r\n return Math.pow(10, Math.max(getPrecision(a), getPrecision(b)))\r\n}\r\n\r\n/**\r\n * Safely adds two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The sum.\r\n */\r\nexport function add(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) + Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely subtracts two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The difference.\r\n */\r\nexport function sub(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) - Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely multiplies two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The product.\r\n */\r\nexport function mul(a: number, b: number): number {\r\n const factorA = toPrecisionFactor(a, 1)\r\n const factorB = toPrecisionFactor(1, b)\r\n const result = (Math.round(a * factorA) * Math.round(b * factorB)) / (factorA * factorB)\r\n return result\r\n}\r\n\r\n/**\r\n * Safely divides two numbers.\r\n *\r\n * @param a - The dividend.\r\n * @param b - The divisor.\r\n * @returns The quotient.\r\n * @throws {DivisionByZeroError} If `b` is zero.\r\n */\r\nexport function div(a: number, b: number): number {\r\n if (b === 0) throw new DivisionByZeroError()\r\n const factor = toPrecisionFactor(a, b)\r\n return Math.round(a * factor) / Math.round(b * factor)\r\n}\r\n\r\n/**\r\n * Rounds a number to the given precision.\r\n *\r\n * @param value - The number to round.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The rounded value.\r\n */\r\nexport function round(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.round(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Floors a number to the given precision.\r\n *\r\n * @param value - The number to floor.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The floored value.\r\n */\r\nexport function floor(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.floor(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Ceils a number to the given precision.\r\n *\r\n * @param value - The number to ceil.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The ceiled value.\r\n */\r\nexport function ceil(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.ceil(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Checks if two numbers are approximately equal within a tolerance.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @param tolerance - Maximum difference (default `Number.EPSILON`).\r\n * @returns Whether the numbers are approximately equal.\r\n */\r\nexport function approxEqual(a: number, b: number, tolerance: number = Number.EPSILON): boolean {\r\n return Math.abs(a - b) <= tolerance\r\n}\r\n\r\n/**\r\n * Clamps a value within the inclusive range [min, max].\r\n *\r\n * @param value - The value to clamp.\r\n * @param min - The lower bound.\r\n * @param max - The upper bound.\r\n * @returns The clamped value.\r\n * @throws {RangeError} If `min` exceeds `max`.\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n if (min > max) {\r\n throw new RangeError('Minimum value cannot exceed maximum value')\r\n }\r\n return Math.min(Math.max(value, min), max)\r\n}\r\n\r\n/**\r\n * Computes the sum of an array of numbers.\r\n *\r\n * @param values - Array of numbers.\r\n * @returns The total sum.\r\n */\r\nexport function sum(values: number[]): number {\r\n let total = 0\r\n for (let i = 0; i < values.length; i++) {\r\n total += values[i]!\r\n }\r\n return total\r\n}\r\n\r\n/**\r\n * Computes the average (mean) of an array of numbers.\r\n *\r\n * @param values - Array of numbers.\r\n * @returns The average.\r\n * @throws {RangeError} If the array is empty.\r\n */\r\nexport function average(values: number[]): number {\r\n if (values.length === 0) {\r\n throw new RangeError('Cannot compute average of an empty array')\r\n }\r\n return sum(values) / values.length\r\n}\r\n\r\n/**\r\n * Generates a random integer between `min` and `max` (inclusive).\r\n *\r\n * @param min - The minimum integer.\r\n * @param max - The maximum integer.\r\n * @returns A random integer.\r\n * @throws {RangeError} If arguments are not integers or `min > max`.\r\n */\r\nexport function randomInt(min: number, max: number): number {\r\n if (!Number.isInteger(min) || !Number.isInteger(max)) {\r\n throw new RangeError('Arguments must be integers')\r\n }\r\n if (min > max) {\r\n throw new RangeError('Minimum value cannot exceed maximum value')\r\n }\r\n return Math.floor(Math.random() * (max - min + 1)) + min\r\n}\r\n\r\n/**\r\n * Checks if a number is within the inclusive range [min, max].\r\n *\r\n * @param value - The number to check.\r\n * @param min - The lower bound.\r\n * @param max - The upper bound.\r\n * @returns Whether the value is in range.\r\n */\r\nexport function inRange(value: number, min: number, max: number): boolean {\r\n return value >= min && value <= max\r\n}\r\n"],"mappings":";AAGO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,cAAc;AACZ,UAAM,kBAAkB;AACxB,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,aAAa,OAAuB;AAC3C,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,QAAM,SAAS,OAAO,KAAK,EAAE,QAAQ,GAAG;AACxC,MAAI,SAAS,IAAI;AACf,UAAM,MAAM,SAAS,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC,GAAG,EAAE;AACxD,QAAI,MAAM,EAAG,QAAO,KAAK,IAAI,GAAG;AAChC,WAAO;AAAA,EACT;AACA,QAAM,MAAM,OAAO,KAAK;AACxB,QAAM,MAAM,IAAI,QAAQ,GAAG;AAC3B,SAAO,QAAQ,KAAK,IAAI,IAAI,SAAS,MAAM;AAC7C;AAEA,SAAS,kBAAkB,GAAW,GAAmB;AACvD,SAAO,KAAK,IAAI,IAAI,KAAK,IAAI,aAAa,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;AAChE;AASO,SAAS,IAAI,GAAW,GAAmB;AAChD,QAAM,SAAS,kBAAkB,GAAG,CAAC;AACrC,UAAQ,KAAK,MAAM,IAAI,MAAM,IAAI,KAAK,MAAM,IAAI,MAAM,KAAK;AAC7D;AASO,SAAS,IAAI,GAAW,GAAmB;AAChD,QAAM,SAAS,kBAAkB,GAAG,CAAC;AACrC,UAAQ,KAAK,MAAM,IAAI,MAAM,IAAI,KAAK,MAAM,IAAI,MAAM,KAAK;AAC7D;AASO,SAAS,IAAI,GAAW,GAAmB;AAChD,QAAM,UAAU,kBAAkB,GAAG,CAAC;AACtC,QAAM,UAAU,kBAAkB,GAAG,CAAC;AACtC,QAAM,SAAU,KAAK,MAAM,IAAI,OAAO,IAAI,KAAK,MAAM,IAAI,OAAO,KAAM,UAAU;AAChF,SAAO;AACT;AAUO,SAAS,IAAI,GAAW,GAAmB;AAChD,MAAI,MAAM,EAAG,OAAM,IAAI,oBAAoB;AAC3C,QAAM,SAAS,kBAAkB,GAAG,CAAC;AACrC,SAAO,KAAK,MAAM,IAAI,MAAM,IAAI,KAAK,MAAM,IAAI,MAAM;AACvD;AASO,SAAS,MAAM,OAAe,YAAoB,GAAW;AAClE,QAAM,SAAS,KAAK,IAAI,IAAI,SAAS;AACrC,SAAO,KAAK,MAAM,QAAQ,MAAM,IAAI;AACtC;AASO,SAAS,MAAM,OAAe,YAAoB,GAAW;AAClE,QAAM,SAAS,KAAK,IAAI,IAAI,SAAS;AACrC,SAAO,KAAK,MAAM,QAAQ,MAAM,IAAI;AACtC;AASO,SAAS,KAAK,OAAe,YAAoB,GAAW;AACjE,QAAM,SAAS,KAAK,IAAI,IAAI,SAAS;AACrC,SAAO,KAAK,KAAK,QAAQ,MAAM,IAAI;AACrC;AAUO,SAAS,YAAY,GAAW,GAAW,YAAoB,OAAO,SAAkB;AAC7F,SAAO,KAAK,IAAI,IAAI,CAAC,KAAK;AAC5B;AAWO,SAAS,MAAM,OAAe,KAAa,KAAqB;AACrE,MAAI,MAAM,KAAK;AACb,UAAM,IAAI,WAAW,2CAA2C;AAAA,EAClE;AACA,SAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,GAAG;AAC3C;AAQO,SAAS,IAAI,QAA0B;AAC5C,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,aAAS,OAAO,CAAC;AAAA,EACnB;AACA,SAAO;AACT;AASO,SAAS,QAAQ,QAA0B;AAChD,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,IAAI,WAAW,0CAA0C;AAAA,EACjE;AACA,SAAO,IAAI,MAAM,IAAI,OAAO;AAC9B;AAUO,SAAS,UAAU,KAAa,KAAqB;AAC1D,MAAI,CAAC,OAAO,UAAU,GAAG,KAAK,CAAC,OAAO,UAAU,GAAG,GAAG;AACpD,UAAM,IAAI,WAAW,4BAA4B;AAAA,EACnD;AACA,MAAI,MAAM,KAAK;AACb,UAAM,IAAI,WAAW,2CAA2C;AAAA,EAClE;AACA,SAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;AACvD;AAUO,SAAS,QAAQ,OAAe,KAAa,KAAsB;AACxE,SAAO,SAAS,OAAO,SAAS;AAClC;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/path/index.ts"],"sourcesContent":["const SEP = '/'\n\n/**\n * Joins path segments with the proper separator.\n *\n * @param segments - Path segments to join.\n * @returns The joined path.\n */\nexport function join(...segments: string[]): string {\n const parts: string[] = []\n for (const seg of segments) {\n if (seg === '') continue\n const split = seg.split(/[\\\\/]/)\n for (const part of split) {\n if (part === '' || part === '.') continue\n if (part === '..') {\n if (parts.length > 0 && parts[parts.length - 1] !== '..') {\n parts.pop()\n } else {\n parts.push('..')\n }\n } else {\n parts.push(part)\n }\n }\n }\n if (parts.length === 0) return '.'\n const result = parts.join(SEP)\n if (segments.length > 0 && segments[0]!.startsWith('/')) {\n return SEP + result\n }\n return result\n}\n\n/**\n * Resolves path segments to an absolute path.\n *\n * @param segments - Path segments to resolve.\n * @returns The resolved absolute path.\n */\nexport function resolve(...segments: string[]): string {\n let resolved = ''\n let isAbs = false\n\n for (const seg of segments) {\n if (seg.startsWith('/')) {\n resolved = seg\n isAbs = true\n } else if (isAbs) {\n resolved = join(resolved, seg)\n } else {\n resolved = resolved ? join(resolved, seg) : seg\n }\n }\n\n if (!isAbs) {\n resolved = join(SEP, resolved)\n }\n\n return normalize(resolved)\n}\n\n/**\n * Returns the filename from a path.\n *\n * @param p - The path.\n * @param ext - Optional extension to strip.\n * @returns The filename.\n */\nexport function basename(p: string, ext?: string): string {\n const normalized = p.replace(/[\\\\/]+$/, '')\n const idx = normalized.lastIndexOf(SEP)\n let base = idx === -1 ? normalized : normalized.slice(idx + 1)\n if (ext && base.endsWith(ext)) {\n base = base.slice(0, -ext.length)\n }\n return base\n}\n\n/**\n * Returns the directory portion of a path.\n *\n * @param p - The path.\n * @returns The directory path.\n */\nexport function dirname(p: string): string {\n if (p === SEP) return SEP\n const normalized = p.replace(/[\\\\/]+$/, '')\n if (normalized === '') return '.'\n const idx = normalized.lastIndexOf(SEP)\n if (idx === -1) return '.'\n if (idx === 0) return SEP\n return normalized.slice(0, idx)\n}\n\n/**\n * Returns the file extension from a path.\n *\n * @param p - The path.\n * @returns The extension including the dot, or empty string.\n */\nexport function extname(p: string): string {\n const base = basename(p)\n const idx = base.lastIndexOf('.')\n if (idx === -1 || idx === 0) return ''\n return base.slice(idx)\n}\n\n/**\n * Normalizes a path, resolving '..' and '.' segments.\n *\n * @param p - The path to normalize.\n * @returns The normalized path.\n */\nexport function normalize(p: string): string {\n const parts = p.split(/[\\\\/]+/)\n const stack: string[] = []\n let isAbs = p.startsWith('/')\n\n for (const part of parts) {\n if (part === '' || part === '.') continue\n if (part === '..') {\n if (stack.length > 0 && stack[stack.length - 1] !== '..') {\n stack.pop()\n } else if (!isAbs) {\n stack.push('..')\n }\n } else {\n stack.push(part)\n }\n }\n\n const result = stack.join(SEP)\n if (isAbs) return SEP + result\n if (result === '') return '.'\n return result\n}\n\n/**\n * Checks if a path is absolute.\n *\n * @param p - The path to check.\n * @returns Whether the path is absolute.\n */\nexport function isAbsolute(p: string): boolean {\n return p.startsWith('/')\n}\n\n/**\n * Computes the relative path from `from` to `to`.\n *\n * @param from - The base path.\n * @param to - The target path.\n * @returns The relative path.\n */\nexport function relative(from: string, to: string): string {\n const fromParts = normalize(from).split(SEP)\n const toParts = normalize(to).split(SEP)\n\n let i = 0\n while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {\n i++\n }\n\n const up = fromParts.slice(i).map(() => '..')\n const down = toParts.slice(i)\n const result = [...up, ...down].join(SEP)\n\n return result || '.'\n}\n\nexport interface ParsedPath {\n root: string\n dir: string\n base: string\n name: string\n ext: string\n}\n\n/**\n * Parses a path into its components.\n *\n * @param p - The path to parse.\n * @returns An object with root, dir, base, name, and ext.\n */\nexport function parse(p: string): ParsedPath {\n const root = p.startsWith(SEP) ? SEP : ''\n const base = basename(p)\n const ext = extname(base)\n const name = ext ? base.slice(0, -ext.length) : base\n const dir = root ? dirname(p) : (dirname(p) === '.' ? '' : dirname(p))\n\n return { root, dir, base, name, ext }\n}\n\n/**\n * Formats a parsed path object back into a path string.\n *\n * @param parsed - The parsed path components.\n * @returns The formatted path string.\n */\nexport function format(parsed: Partial<ParsedPath>): string {\n const { root = '', dir = '', base = '', name = '', ext = '' } = parsed\n const baseName = base || name + ext\n if (dir) {\n return dir + SEP + baseName\n }\n return root + baseName\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/path/index.ts"],"sourcesContent":["const SEP = '/'\r\n\r\n/**\r\n * Joins path segments with the proper separator.\r\n *\r\n * @param segments - Path segments to join.\r\n * @returns The joined path.\r\n */\r\nexport function join(...segments: string[]): string {\r\n const parts: string[] = []\r\n for (const seg of segments) {\r\n if (seg === '') continue\r\n const split = seg.split(/[\\\\/]/)\r\n for (const part of split) {\r\n if (part === '' || part === '.') continue\r\n if (part === '..') {\r\n if (parts.length > 0 && parts[parts.length - 1] !== '..') {\r\n parts.pop()\r\n } else {\r\n parts.push('..')\r\n }\r\n } else {\r\n parts.push(part)\r\n }\r\n }\r\n }\r\n if (parts.length === 0) return '.'\r\n const result = parts.join(SEP)\r\n if (segments.length > 0 && segments[0]!.startsWith('/')) {\r\n return SEP + result\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Resolves path segments to an absolute path.\r\n *\r\n * @param segments - Path segments to resolve.\r\n * @returns The resolved absolute path.\r\n */\r\nexport function resolve(...segments: string[]): string {\r\n let resolved = ''\r\n let isAbs = false\r\n\r\n for (const seg of segments) {\r\n if (seg.startsWith('/')) {\r\n resolved = seg\r\n isAbs = true\r\n } else if (isAbs) {\r\n resolved = join(resolved, seg)\r\n } else {\r\n resolved = resolved ? join(resolved, seg) : seg\r\n }\r\n }\r\n\r\n if (!isAbs) {\r\n resolved = join(SEP, resolved)\r\n }\r\n\r\n return normalize(resolved)\r\n}\r\n\r\n/**\r\n * Returns the filename from a path.\r\n *\r\n * @param p - The path.\r\n * @param ext - Optional extension to strip.\r\n * @returns The filename.\r\n */\r\nexport function basename(p: string, ext?: string): string {\r\n const normalized = p.replace(/[\\\\/]+$/, '')\r\n const idx = normalized.lastIndexOf(SEP)\r\n let base = idx === -1 ? normalized : normalized.slice(idx + 1)\r\n if (ext && base.endsWith(ext)) {\r\n base = base.slice(0, -ext.length)\r\n }\r\n return base\r\n}\r\n\r\n/**\r\n * Returns the directory portion of a path.\r\n *\r\n * @param p - The path.\r\n * @returns The directory path.\r\n */\r\nexport function dirname(p: string): string {\r\n if (p === SEP) return SEP\r\n const normalized = p.replace(/[\\\\/]+$/, '')\r\n if (normalized === '') return '.'\r\n const idx = normalized.lastIndexOf(SEP)\r\n if (idx === -1) return '.'\r\n if (idx === 0) return SEP\r\n return normalized.slice(0, idx)\r\n}\r\n\r\n/**\r\n * Returns the file extension from a path.\r\n *\r\n * @param p - The path.\r\n * @returns The extension including the dot, or empty string.\r\n */\r\nexport function extname(p: string): string {\r\n const base = basename(p)\r\n const idx = base.lastIndexOf('.')\r\n if (idx === -1 || idx === 0) return ''\r\n return base.slice(idx)\r\n}\r\n\r\n/**\r\n * Normalizes a path, resolving '..' and '.' segments.\r\n *\r\n * @param p - The path to normalize.\r\n * @returns The normalized path.\r\n */\r\nexport function normalize(p: string): string {\r\n const parts = p.split(/[\\\\/]+/)\r\n const stack: string[] = []\r\n let isAbs = p.startsWith('/')\r\n\r\n for (const part of parts) {\r\n if (part === '' || part === '.') continue\r\n if (part === '..') {\r\n if (stack.length > 0 && stack[stack.length - 1] !== '..') {\r\n stack.pop()\r\n } else if (!isAbs) {\r\n stack.push('..')\r\n }\r\n } else {\r\n stack.push(part)\r\n }\r\n }\r\n\r\n const result = stack.join(SEP)\r\n if (isAbs) return SEP + result\r\n if (result === '') return '.'\r\n return result\r\n}\r\n\r\n/**\r\n * Checks if a path is absolute.\r\n *\r\n * @param p - The path to check.\r\n * @returns Whether the path is absolute.\r\n */\r\nexport function isAbsolute(p: string): boolean {\r\n return p.startsWith('/')\r\n}\r\n\r\n/**\r\n * Computes the relative path from `from` to `to`.\r\n *\r\n * @param from - The base path.\r\n * @param to - The target path.\r\n * @returns The relative path.\r\n */\r\nexport function relative(from: string, to: string): string {\r\n const fromParts = normalize(from).split(SEP)\r\n const toParts = normalize(to).split(SEP)\r\n\r\n let i = 0\r\n while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {\r\n i++\r\n }\r\n\r\n const up = fromParts.slice(i).map(() => '..')\r\n const down = toParts.slice(i)\r\n const result = [...up, ...down].join(SEP)\r\n\r\n return result || '.'\r\n}\r\n\r\nexport interface ParsedPath {\r\n root: string\r\n dir: string\r\n base: string\r\n name: string\r\n ext: string\r\n}\r\n\r\n/**\r\n * Parses a path into its components.\r\n *\r\n * @param p - The path to parse.\r\n * @returns An object with root, dir, base, name, and ext.\r\n */\r\nexport function parse(p: string): ParsedPath {\r\n const root = p.startsWith(SEP) ? SEP : ''\r\n const base = basename(p)\r\n const ext = extname(base)\r\n const name = ext ? base.slice(0, -ext.length) : base\r\n const dir = root ? dirname(p) : (dirname(p) === '.' ? '' : dirname(p))\r\n\r\n return { root, dir, base, name, ext }\r\n}\r\n\r\n/**\r\n * Formats a parsed path object back into a path string.\r\n *\r\n * @param parsed - The parsed path components.\r\n * @returns The formatted path string.\r\n */\r\nexport function format(parsed: Partial<ParsedPath>): string {\r\n const { root = '', dir = '', base = '', name = '', ext = '' } = parsed\r\n const baseName = base || name + ext\r\n if (dir) {\r\n return dir + SEP + baseName\r\n }\r\n return root + baseName\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/string/index.ts"],"sourcesContent":["const WORD_SPLIT_RE = /[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\\d|\\b)|\\d+/g\n\nfunction splitWords(str: string): string[] {\n return str.match(WORD_SPLIT_RE) ?? []\n}\n\n/**\n * Capitalizes the first character and lowercases the rest.\n */\nexport function capitalize(str: string): string {\n if (str.length === 0) return str\n return str[0]!.toUpperCase() + str.slice(1).toLowerCase()\n}\n\n/**\n * Converts a string to camelCase.\n */\nexport function camelCase(str: string): string {\n const words = splitWords(str)\n if (words.length === 0) return ''\n const [firstWord, ...rest] = words\n return firstWord!.toLowerCase() + rest.map(w => w[0]!.toUpperCase() + w.slice(1).toLowerCase()).join('')\n}\n\n/**\n * Converts a string to kebab-case.\n */\nexport function kebabCase(str: string): string {\n return splitWords(str).map(w => w.toLowerCase()).join('-')\n}\n\n/**\n * Converts a string to snake_case.\n */\nexport function snakeCase(str: string): string {\n return splitWords(str).map(w => w.toLowerCase()).join('_')\n}\n\n/**\n * Converts a string to PascalCase.\n */\nexport function pascalCase(str: string): string {\n return splitWords(str).map(w => w[0]!.toUpperCase() + w.slice(1).toLowerCase()).join('')\n}\n\n/**\n * Truncates a string to the specified length, appending a suffix (default \"...\").\n */\nexport function truncate(str: string, maxLength: number, suffix = '...'): string {\n if (str.length <= maxLength) return str\n return str.slice(0, Math.max(0, maxLength - suffix.length)) + suffix\n}\n\n/**\n * Simple string interpolation using {{key}} syntax.\n *\n * @example template(\"Hello {{name}}\", { name: \"world\" }) // => \"Hello world\"\n */\nexport function template(str: string, data: Record<string, string | number>): string {\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => {\n const value = data[key]\n return value !== undefined ? String(value) : `{{${key}}}`\n })\n}\n\n/**\n * Generates a UUID v4 string.\n * Uses crypto.randomUUID when available, falls back to manual implementation.\n */\nexport function uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n const hex = '0123456789abcdef'\n const chars: string[] = []\n for (let i = 0; i < 36; i++) {\n if (i === 8 || i === 13 || i === 18 || i === 23) {\n chars.push('-')\n } else if (i === 14) {\n chars.push('4')\n } else if (i === 19) {\n chars.push(hex[Math.floor(Math.random() * 4) + 8]!)\n } else {\n chars.push(hex[Math.floor(Math.random() * 16)]!)\n }\n }\n return chars.join('')\n}\n\n/**\n * Generates a short random ID with configurable length and alphabet.\n *\n * @default size = 21, alphabet = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-\"\n */\nexport function nanoid(size = 21, alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-'): string {\n const len = alphabet.length\n let result = ''\n for (let i = 0; i < size; i++) {\n result += alphabet[Math.floor(Math.random() * len)]!\n }\n return result\n}\n\nconst HTML_ESCAPE_MAP: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n}\n\nconst HTML_UNESCAPE_MAP: Record<string, string> = {\n '&amp;': '&',\n '&lt;': '<',\n '&gt;': '>',\n '&quot;': '\"',\n '&#39;': \"'\",\n '&#x27;': \"'\",\n}\n\n/**\n * Escapes HTML special characters (&, <, >, \", ').\n */\nexport function escapeHtml(str: string): string {\n return str.replace(/[&<>\"']/g, ch => HTML_ESCAPE_MAP[ch] ?? ch)\n}\n\n/**\n * Unescapes common HTML entities.\n */\nexport function unescapeHtml(str: string): string {\n return str.replace(/&(?:amp|lt|gt|quot|#39|#x27);/g, entity => HTML_UNESCAPE_MAP[entity] ?? entity)\n}\n\n/**\n * Removes whitespace from both ends of a string.\n */\nexport function trim(str: string): string {\n return str.trim()\n}\n\n/**\n * Removes whitespace from the start of a string.\n */\nexport function trimStart(str: string): string {\n return str.trimStart()\n}\n\n/**\n * Removes whitespace from the end of a string.\n */\nexport function trimEnd(str: string): string {\n return str.trimEnd()\n}\n\n/**\n * Pads a string to the given length by adding characters to both sides.\n */\nexport function pad(str: string, length: number, char = ' '): string {\n const totalPadding = Math.max(0, length - str.length)\n const leftPad = Math.floor(totalPadding / 2)\n const rightPad = totalPadding - leftPad\n return char.repeat(leftPad) + str + char.repeat(rightPad)\n}\n\n/**\n * Pads the start of a string to the given length.\n */\nexport function padStart(str: string, length: number, char = ' '): string {\n return str.padStart(length, char)\n}\n\n/**\n * Pads the end of a string to the given length.\n */\nexport function padEnd(str: string, length: number, char = ' '): string {\n return str.padEnd(length, char)\n}\n\n/**\n * Reverses a string.\n */\nexport function reverse(str: string): string {\n return str.split('').reverse().join('')\n}\n\n/**\n * Splits a string into words.\n */\nexport function words(str: string): string[] {\n return splitWords(str)\n}\n\n/**\n * Converts a string to a URL-friendly slug.\n */\nexport function slugify(str: string): string {\n return str\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-+/, '')\n .replace(/-+$/, '')\n}\n\n/**\n * Counts occurrences of a substring in a string.\n */\nexport function countOccurrences(str: string, substring: string): number {\n if (substring.length === 0 || str.length === 0) return 0\n let count = 0\n let pos = 0\n while ((pos = str.indexOf(substring, pos)) !== -1) {\n count++\n pos += substring.length\n }\n return count\n}\n"],"mappings":";AAAA,IAAM,gBAAgB;AAEtB,SAAS,WAAW,KAAuB;AACzC,SAAO,IAAI,MAAM,aAAa,KAAK,CAAC;AACtC;AAKO,SAAS,WAAW,KAAqB;AAC9C,MAAI,IAAI,WAAW,EAAG,QAAO;AAC7B,SAAO,IAAI,CAAC,EAAG,YAAY,IAAI,IAAI,MAAM,CAAC,EAAE,YAAY;AAC1D;AAKO,SAAS,UAAU,KAAqB;AAC7C,QAAMA,SAAQ,WAAW,GAAG;AAC5B,MAAIA,OAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,CAAC,WAAW,GAAG,IAAI,IAAIA;AAC7B,SAAO,UAAW,YAAY,IAAI,KAAK,IAAI,OAAK,EAAE,CAAC,EAAG,YAAY,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,EAAE,KAAK,EAAE;AACzG;AAKO,SAAS,UAAU,KAAqB;AAC7C,SAAO,WAAW,GAAG,EAAE,IAAI,OAAK,EAAE,YAAY,CAAC,EAAE,KAAK,GAAG;AAC3D;AAKO,SAAS,UAAU,KAAqB;AAC7C,SAAO,WAAW,GAAG,EAAE,IAAI,OAAK,EAAE,YAAY,CAAC,EAAE,KAAK,GAAG;AAC3D;AAKO,SAAS,WAAW,KAAqB;AAC9C,SAAO,WAAW,GAAG,EAAE,IAAI,OAAK,EAAE,CAAC,EAAG,YAAY,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,EAAE,KAAK,EAAE;AACzF;AAKO,SAAS,SAAS,KAAa,WAAmB,SAAS,OAAe;AAC/E,MAAI,IAAI,UAAU,UAAW,QAAO;AACpC,SAAO,IAAI,MAAM,GAAG,KAAK,IAAI,GAAG,YAAY,OAAO,MAAM,CAAC,IAAI;AAChE;AAOO,SAAS,SAAS,KAAa,MAA+C;AACnF,SAAO,IAAI,QAAQ,kBAAkB,CAAC,GAAG,QAAgB;AACvD,UAAM,QAAQ,KAAK,GAAG;AACtB,WAAO,UAAU,SAAY,OAAO,KAAK,IAAI,KAAK,GAAG;AAAA,EACvD,CAAC;AACH;AAMO,SAAS,OAAe;AAC7B,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAC5E,WAAO,OAAO,WAAW;AAAA,EAC3B;AACA,QAAM,MAAM;AACZ,QAAM,QAAkB,CAAC;AACzB,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,QAAI,MAAM,KAAK,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAC/C,YAAM,KAAK,GAAG;AAAA,IAChB,WAAW,MAAM,IAAI;AACnB,YAAM,KAAK,GAAG;AAAA,IAChB,WAAW,MAAM,IAAI;AACnB,YAAM,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,CAAE;AAAA,IACpD,OAAO;AACL,YAAM,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,CAAC,CAAE;AAAA,IACjD;AAAA,EACF;AACA,SAAO,MAAM,KAAK,EAAE;AACtB;AAOO,SAAS,OAAO,OAAO,IAAI,WAAW,oEAA4E;AACvH,QAAM,MAAM,SAAS;AACrB,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,cAAU,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG,CAAC;AAAA,EACpD;AACA,SAAO;AACT;AAEA,IAAM,kBAA0C;AAAA,EAC9C,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAEA,IAAM,oBAA4C;AAAA,EAChD,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AACZ;AAKO,SAAS,WAAW,KAAqB;AAC9C,SAAO,IAAI,QAAQ,YAAY,QAAM,gBAAgB,EAAE,KAAK,EAAE;AAChE;AAKO,SAAS,aAAa,KAAqB;AAChD,SAAO,IAAI,QAAQ,kCAAkC,YAAU,kBAAkB,MAAM,KAAK,MAAM;AACpG;AAKO,SAAS,KAAK,KAAqB;AACxC,SAAO,IAAI,KAAK;AAClB;AAKO,SAAS,UAAU,KAAqB;AAC7C,SAAO,IAAI,UAAU;AACvB;AAKO,SAAS,QAAQ,KAAqB;AAC3C,SAAO,IAAI,QAAQ;AACrB;AAKO,SAAS,IAAI,KAAa,QAAgB,OAAO,KAAa;AACnE,QAAM,eAAe,KAAK,IAAI,GAAG,SAAS,IAAI,MAAM;AACpD,QAAM,UAAU,KAAK,MAAM,eAAe,CAAC;AAC3C,QAAM,WAAW,eAAe;AAChC,SAAO,KAAK,OAAO,OAAO,IAAI,MAAM,KAAK,OAAO,QAAQ;AAC1D;AAKO,SAAS,SAAS,KAAa,QAAgB,OAAO,KAAa;AACxE,SAAO,IAAI,SAAS,QAAQ,IAAI;AAClC;AAKO,SAAS,OAAO,KAAa,QAAgB,OAAO,KAAa;AACtE,SAAO,IAAI,OAAO,QAAQ,IAAI;AAChC;AAKO,SAAS,QAAQ,KAAqB;AAC3C,SAAO,IAAI,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;AACxC;AAKO,SAAS,MAAM,KAAuB;AAC3C,SAAO,WAAW,GAAG;AACvB;AAKO,SAAS,QAAQ,KAAqB;AAC3C,SAAO,IACJ,YAAY,EACZ,QAAQ,aAAa,EAAE,EACvB,QAAQ,WAAW,GAAG,EACtB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,EAAE,EACjB,QAAQ,OAAO,EAAE;AACtB;AAKO,SAAS,iBAAiB,KAAa,WAA2B;AACvE,MAAI,UAAU,WAAW,KAAK,IAAI,WAAW,EAAG,QAAO;AACvD,MAAI,QAAQ;AACZ,MAAI,MAAM;AACV,UAAQ,MAAM,IAAI,QAAQ,WAAW,GAAG,OAAO,IAAI;AACjD;AACA,WAAO,UAAU;AAAA,EACnB;AACA,SAAO;AACT;","names":["words"]}
1
+ {"version":3,"sources":["../../src/string/index.ts"],"sourcesContent":["const WORD_SPLIT_RE = /[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\\d|\\b)|\\d+/g\r\n\r\nfunction splitWords(str: string): string[] {\r\n return str.match(WORD_SPLIT_RE) ?? []\r\n}\r\n\r\n/**\r\n * Capitalizes the first character and lowercases the rest.\r\n */\r\nexport function capitalize(str: string): string {\r\n if (str.length === 0) return str\r\n return str[0]!.toUpperCase() + str.slice(1).toLowerCase()\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n */\r\nexport function camelCase(str: string): string {\r\n const words = splitWords(str)\r\n if (words.length === 0) return ''\r\n const [firstWord, ...rest] = words\r\n return firstWord!.toLowerCase() + rest.map(w => w[0]!.toUpperCase() + w.slice(1).toLowerCase()).join('')\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n */\r\nexport function kebabCase(str: string): string {\r\n return splitWords(str).map(w => w.toLowerCase()).join('-')\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n */\r\nexport function snakeCase(str: string): string {\r\n return splitWords(str).map(w => w.toLowerCase()).join('_')\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n */\r\nexport function pascalCase(str: string): string {\r\n return splitWords(str).map(w => w[0]!.toUpperCase() + w.slice(1).toLowerCase()).join('')\r\n}\r\n\r\n/**\r\n * Truncates a string to the specified length, appending a suffix (default \"...\").\r\n */\r\nexport function truncate(str: string, maxLength: number, suffix = '...'): string {\r\n if (str.length <= maxLength) return str\r\n return str.slice(0, Math.max(0, maxLength - suffix.length)) + suffix\r\n}\r\n\r\n/**\r\n * Simple string interpolation using {{key}} syntax.\r\n *\r\n * @example template(\"Hello {{name}}\", { name: \"world\" }) // => \"Hello world\"\r\n */\r\nexport function template(str: string, data: Record<string, string | number>): string {\r\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => {\r\n const value = data[key]\r\n return value !== undefined ? String(value) : `{{${key}}}`\r\n })\r\n}\r\n\r\n/**\r\n * Generates a UUID v4 string.\r\n * Uses crypto.randomUUID when available, falls back to manual implementation.\r\n */\r\nexport function uuid(): string {\r\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID()\r\n }\r\n const hex = '0123456789abcdef'\r\n const chars: string[] = []\r\n for (let i = 0; i < 36; i++) {\r\n if (i === 8 || i === 13 || i === 18 || i === 23) {\r\n chars.push('-')\r\n } else if (i === 14) {\r\n chars.push('4')\r\n } else if (i === 19) {\r\n chars.push(hex[Math.floor(Math.random() * 4) + 8]!)\r\n } else {\r\n chars.push(hex[Math.floor(Math.random() * 16)]!)\r\n }\r\n }\r\n return chars.join('')\r\n}\r\n\r\n/**\r\n * Generates a short random ID with configurable length and alphabet.\r\n *\r\n * @default size = 21, alphabet = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-\"\r\n */\r\nexport function nanoid(size = 21, alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-'): string {\r\n const len = alphabet.length\r\n let result = ''\r\n for (let i = 0; i < size; i++) {\r\n result += alphabet[Math.floor(Math.random() * len)]!\r\n }\r\n return result\r\n}\r\n\r\nconst HTML_ESCAPE_MAP: Record<string, string> = {\r\n '&': '&amp;',\r\n '<': '&lt;',\r\n '>': '&gt;',\r\n '\"': '&quot;',\r\n \"'\": '&#39;',\r\n}\r\n\r\nconst HTML_UNESCAPE_MAP: Record<string, string> = {\r\n '&amp;': '&',\r\n '&lt;': '<',\r\n '&gt;': '>',\r\n '&quot;': '\"',\r\n '&#39;': \"'\",\r\n '&#x27;': \"'\",\r\n}\r\n\r\n/**\r\n * Escapes HTML special characters (&, <, >, \", ').\r\n */\r\nexport function escapeHtml(str: string): string {\r\n return str.replace(/[&<>\"']/g, ch => HTML_ESCAPE_MAP[ch] ?? ch)\r\n}\r\n\r\n/**\r\n * Unescapes common HTML entities.\r\n */\r\nexport function unescapeHtml(str: string): string {\r\n return str.replace(/&(?:amp|lt|gt|quot|#39|#x27);/g, entity => HTML_UNESCAPE_MAP[entity] ?? entity)\r\n}\r\n\r\n/**\r\n * Removes whitespace from both ends of a string.\r\n */\r\nexport function trim(str: string): string {\r\n return str.trim()\r\n}\r\n\r\n/**\r\n * Removes whitespace from the start of a string.\r\n */\r\nexport function trimStart(str: string): string {\r\n return str.trimStart()\r\n}\r\n\r\n/**\r\n * Removes whitespace from the end of a string.\r\n */\r\nexport function trimEnd(str: string): string {\r\n return str.trimEnd()\r\n}\r\n\r\n/**\r\n * Pads a string to the given length by adding characters to both sides.\r\n */\r\nexport function pad(str: string, length: number, char = ' '): string {\r\n const totalPadding = Math.max(0, length - str.length)\r\n const leftPad = Math.floor(totalPadding / 2)\r\n const rightPad = totalPadding - leftPad\r\n return char.repeat(leftPad) + str + char.repeat(rightPad)\r\n}\r\n\r\n/**\r\n * Pads the start of a string to the given length.\r\n */\r\nexport function padStart(str: string, length: number, char = ' '): string {\r\n return str.padStart(length, char)\r\n}\r\n\r\n/**\r\n * Pads the end of a string to the given length.\r\n */\r\nexport function padEnd(str: string, length: number, char = ' '): string {\r\n return str.padEnd(length, char)\r\n}\r\n\r\n/**\r\n * Reverses a string.\r\n */\r\nexport function reverse(str: string): string {\r\n return str.split('').reverse().join('')\r\n}\r\n\r\n/**\r\n * Splits a string into words.\r\n */\r\nexport function words(str: string): string[] {\r\n return splitWords(str)\r\n}\r\n\r\n/**\r\n * Converts a string to a URL-friendly slug.\r\n */\r\nexport function slugify(str: string): string {\r\n return str\r\n .toLowerCase()\r\n .replace(/[^\\w\\s-]/g, '')\r\n .replace(/[\\s_]+/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/^-+/, '')\r\n .replace(/-+$/, '')\r\n}\r\n\r\n/**\r\n * Counts occurrences of a substring in a string.\r\n */\r\nexport function countOccurrences(str: string, substring: string): number {\r\n if (substring.length === 0 || str.length === 0) return 0\r\n let count = 0\r\n let pos = 0\r\n while ((pos = str.indexOf(substring, pos)) !== -1) {\r\n count++\r\n pos += substring.length\r\n }\r\n return count\r\n}\r\n"],"mappings":"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","names":["words"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/type/index.ts"],"sourcesContent":["/**\n * Checks if a value is a string.\n */\nexport function isString(value: unknown): value is string {\n return typeof value === 'string'\n}\n\n/**\n * Checks if a value is a number (not NaN, not Infinity).\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n\n/**\n * Checks if a value is a boolean.\n */\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean'\n}\n\n/**\n * Checks if a value is a plain object (not null, not array, typeof 'object').\n */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\n/**\n * Checks if a value is an array.\n */\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value)\n}\n\n/**\n * Checks if a value is a function.\n */\nexport function isFunction(value: unknown): value is (...args: unknown[]) => unknown {\n return typeof value === 'function'\n}\n\n/**\n * Checks if a value is a Date.\n */\nexport function isDate(value: unknown): value is Date {\n return value instanceof Date && !Number.isNaN(value.getTime())\n}\n\n/**\n * Checks if a value is a RegExp.\n */\nexport function isRegExp(value: unknown): value is RegExp {\n return value instanceof RegExp\n}\n\n/**\n * Checks if a value is a Map.\n */\nexport function isMap(value: unknown): value is Map<unknown, unknown> {\n return value instanceof Map\n}\n\n/**\n * Checks if a value is a Set.\n */\nexport function isSet(value: unknown): value is Set<unknown> {\n return value instanceof Set\n}\n\n/**\n * Checks if a value is a Promise.\n */\nexport function isPromise(value: unknown): value is Promise<unknown> {\n return value instanceof Promise\n}\n\n/**\n * Checks if a value is null.\n */\nexport function isNull(value: unknown): value is null {\n return value === null\n}\n\n/**\n * Checks if a value is undefined.\n */\nexport function isUndefined(value: unknown): value is undefined {\n return value === undefined\n}\n\n/**\n * Checks if a value is null or undefined.\n */\nexport function isNil(value: unknown): value is null | undefined {\n return value === null || value === undefined\n}\n\n/**\n * Checks if a value is empty.\n * Works for strings, arrays, objects, Map, and Set.\n */\nexport function isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'string') return value.length === 0\n if (Array.isArray(value)) return value.length === 0\n if (value instanceof Map || value instanceof Set) return value.size === 0\n if (typeof value === 'object') return Object.keys(value as Record<string, unknown>).length === 0\n return false\n}\n\n/**\n * Asserts that a value is defined (not null or undefined).\n * Throws if the value is null or undefined.\n */\nexport function assertDefined<T>(value: T, message?: string): asserts value is NonNullable<T> {\n if (value === null || value === undefined) {\n throw new Error(message ?? 'Expected value to be defined')\n }\n}\n\n/**\n * Asserts that a value matches a type guard. Throws if it doesn't.\n */\nexport function assertType<T>(value: unknown, guard: (v: unknown) => v is T, message?: string): asserts value is T {\n if (!guard(value)) {\n throw new Error(message ?? 'Value does not match expected type')\n }\n}\n\n/**\n * Wraps a value in an array if it is not already one.\n */\nexport function ensureArray<T>(value: T | T[]): T[] {\n return Array.isArray(value) ? value : [value]\n}\n\n/**\n * Alias for ensureArray.\n */\nexport function castArray<T>(value: T | T[]): T[] {\n return ensureArray(value)\n}\n\n/**\n * Returns a string representation of the value's type.\n *\n * Possible values: \"string\", \"number\", \"boolean\", \"array\", \"object\", \"function\",\n * \"date\", \"regexp\", \"map\", \"set\", \"promise\", \"null\", \"undefined\", \"nan\", \"infinity\"\n */\nexport function getType(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (typeof value === 'string') return 'string'\n if (typeof value === 'boolean') return 'boolean'\n if (typeof value === 'function') return 'function'\n if (typeof value === 'number') {\n if (Number.isNaN(value)) return 'nan'\n if (!Number.isFinite(value)) return 'infinity'\n return 'number'\n }\n if (Array.isArray(value)) return 'array'\n if (value instanceof Date) return 'date'\n if (value instanceof RegExp) return 'regexp'\n if (value instanceof Map) return 'map'\n if (value instanceof Set) return 'set'\n if (value instanceof Promise) return 'promise'\n return 'object'\n}\n"],"mappings":";AAGO,SAAS,SAAS,OAAiC;AACxD,SAAO,OAAO,UAAU;AAC1B;AAKO,SAAS,SAAS,OAAiC;AACxD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK;AAC3D;AAKO,SAAS,UAAU,OAAkC;AAC1D,SAAO,OAAO,UAAU;AAC1B;AAKO,SAAS,SAAS,OAAkD;AACzE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAKO,SAAS,QAAQ,OAAoC;AAC1D,SAAO,MAAM,QAAQ,KAAK;AAC5B;AAKO,SAAS,WAAW,OAA0D;AACnF,SAAO,OAAO,UAAU;AAC1B;AAKO,SAAS,OAAO,OAA+B;AACpD,SAAO,iBAAiB,QAAQ,CAAC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC/D;AAKO,SAAS,SAAS,OAAiC;AACxD,SAAO,iBAAiB;AAC1B;AAKO,SAAS,MAAM,OAAgD;AACpE,SAAO,iBAAiB;AAC1B;AAKO,SAAS,MAAM,OAAuC;AAC3D,SAAO,iBAAiB;AAC1B;AAKO,SAAS,UAAU,OAA2C;AACnE,SAAO,iBAAiB;AAC1B;AAKO,SAAS,OAAO,OAA+B;AACpD,SAAO,UAAU;AACnB;AAKO,SAAS,YAAY,OAAoC;AAC9D,SAAO,UAAU;AACnB;AAKO,SAAS,MAAM,OAA2C;AAC/D,SAAO,UAAU,QAAQ,UAAU;AACrC;AAMO,SAAS,QAAQ,OAAyB;AAC/C,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,WAAW;AACvD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,WAAW;AAClD,MAAI,iBAAiB,OAAO,iBAAiB,IAAK,QAAO,MAAM,SAAS;AACxE,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,KAAgC,EAAE,WAAW;AAC/F,SAAO;AACT;AAMO,SAAS,cAAiB,OAAU,SAAmD;AAC5F,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,UAAM,IAAI,MAAM,WAAW,8BAA8B;AAAA,EAC3D;AACF;AAKO,SAAS,WAAc,OAAgB,OAA+B,SAAsC;AACjH,MAAI,CAAC,MAAM,KAAK,GAAG;AACjB,UAAM,IAAI,MAAM,WAAW,oCAAoC;AAAA,EACjE;AACF;AAKO,SAAS,YAAe,OAAqB;AAClD,SAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAC9C;AAKO,SAAS,UAAa,OAAqB;AAChD,SAAO,YAAY,KAAK;AAC1B;AAQO,SAAS,QAAQ,OAAwB;AAC9C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,UAAW,QAAO;AACvC,MAAI,OAAO,UAAU,WAAY,QAAO;AACxC,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,OAAO,MAAM,KAAK,EAAG,QAAO;AAChC,QAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,iBAAiB,KAAM,QAAO;AAClC,MAAI,iBAAiB,OAAQ,QAAO;AACpC,MAAI,iBAAiB,IAAK,QAAO;AACjC,MAAI,iBAAiB,IAAK,QAAO;AACjC,MAAI,iBAAiB,QAAS,QAAO;AACrC,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/type/index.ts"],"sourcesContent":["/**\r\n * Checks if a value is a string.\r\n */\r\nexport function isString(value: unknown): value is string {\r\n return typeof value === 'string'\r\n}\r\n\r\n/**\r\n * Checks if a value is a number (not NaN, not Infinity).\r\n */\r\nexport function isNumber(value: unknown): value is number {\r\n return typeof value === 'number' && Number.isFinite(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is a boolean.\r\n */\r\nexport function isBoolean(value: unknown): value is boolean {\r\n return typeof value === 'boolean'\r\n}\r\n\r\n/**\r\n * Checks if a value is a plain object (not null, not array, typeof 'object').\r\n */\r\nexport function isObject(value: unknown): value is Record<string, unknown> {\r\n return value !== null && typeof value === 'object' && !Array.isArray(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is an array.\r\n */\r\nexport function isArray(value: unknown): value is unknown[] {\r\n return Array.isArray(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is a function.\r\n */\r\nexport function isFunction(value: unknown): value is (...args: unknown[]) => unknown {\r\n return typeof value === 'function'\r\n}\r\n\r\n/**\r\n * Checks if a value is a Date.\r\n */\r\nexport function isDate(value: unknown): value is Date {\r\n return value instanceof Date && !Number.isNaN(value.getTime())\r\n}\r\n\r\n/**\r\n * Checks if a value is a RegExp.\r\n */\r\nexport function isRegExp(value: unknown): value is RegExp {\r\n return value instanceof RegExp\r\n}\r\n\r\n/**\r\n * Checks if a value is a Map.\r\n */\r\nexport function isMap(value: unknown): value is Map<unknown, unknown> {\r\n return value instanceof Map\r\n}\r\n\r\n/**\r\n * Checks if a value is a Set.\r\n */\r\nexport function isSet(value: unknown): value is Set<unknown> {\r\n return value instanceof Set\r\n}\r\n\r\n/**\r\n * Checks if a value is a Promise.\r\n */\r\nexport function isPromise(value: unknown): value is Promise<unknown> {\r\n return value instanceof Promise\r\n}\r\n\r\n/**\r\n * Checks if a value is null.\r\n */\r\nexport function isNull(value: unknown): value is null {\r\n return value === null\r\n}\r\n\r\n/**\r\n * Checks if a value is undefined.\r\n */\r\nexport function isUndefined(value: unknown): value is undefined {\r\n return value === undefined\r\n}\r\n\r\n/**\r\n * Checks if a value is null or undefined.\r\n */\r\nexport function isNil(value: unknown): value is null | undefined {\r\n return value === null || value === undefined\r\n}\r\n\r\n/**\r\n * Checks if a value is empty.\r\n * Works for strings, arrays, objects, Map, and Set.\r\n */\r\nexport function isEmpty(value: unknown): boolean {\r\n if (value === null || value === undefined) return true\r\n if (typeof value === 'string') return value.length === 0\r\n if (Array.isArray(value)) return value.length === 0\r\n if (value instanceof Map || value instanceof Set) return value.size === 0\r\n if (typeof value === 'object') return Object.keys(value as Record<string, unknown>).length === 0\r\n return false\r\n}\r\n\r\n/**\r\n * Asserts that a value is defined (not null or undefined).\r\n * Throws if the value is null or undefined.\r\n */\r\nexport function assertDefined<T>(value: T, message?: string): asserts value is NonNullable<T> {\r\n if (value === null || value === undefined) {\r\n throw new Error(message ?? 'Expected value to be defined')\r\n }\r\n}\r\n\r\n/**\r\n * Asserts that a value matches a type guard. Throws if it doesn't.\r\n */\r\nexport function assertType<T>(value: unknown, guard: (v: unknown) => v is T, message?: string): asserts value is T {\r\n if (!guard(value)) {\r\n throw new Error(message ?? 'Value does not match expected type')\r\n }\r\n}\r\n\r\n/**\r\n * Wraps a value in an array if it is not already one.\r\n */\r\nexport function ensureArray<T>(value: T | T[]): T[] {\r\n return Array.isArray(value) ? value : [value]\r\n}\r\n\r\n/**\r\n * Alias for ensureArray.\r\n */\r\nexport function castArray<T>(value: T | T[]): T[] {\r\n return ensureArray(value)\r\n}\r\n\r\n/**\r\n * Returns a string representation of the value's type.\r\n *\r\n * Possible values: \"string\", \"number\", \"boolean\", \"array\", \"object\", \"function\",\r\n * \"date\", \"regexp\", \"map\", \"set\", \"promise\", \"null\", \"undefined\", \"nan\", \"infinity\"\r\n */\r\nexport function getType(value: unknown): string {\r\n if (value === null) return 'null'\r\n if (value === undefined) return 'undefined'\r\n if (typeof value === 'string') return 'string'\r\n if (typeof value === 'boolean') return 'boolean'\r\n if (typeof value === 'function') return 'function'\r\n if (typeof value === 'number') {\r\n if (Number.isNaN(value)) return 'nan'\r\n if (!Number.isFinite(value)) return 'infinity'\r\n return 'number'\r\n }\r\n if (Array.isArray(value)) return 'array'\r\n if (value instanceof Date) return 'date'\r\n if (value instanceof RegExp) return 'regexp'\r\n if (value instanceof Map) return 'map'\r\n if (value instanceof Set) return 'set'\r\n if (value instanceof Promise) return 'promise'\r\n return 'object'\r\n}\r\n"],"mappings":";AAGO,SAAS,SAAS,OAAiC;AACxD,SAAO,OAAO,UAAU;AAC1B;AAKO,SAAS,SAAS,OAAiC;AACxD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK;AAC3D;AAKO,SAAS,UAAU,OAAkC;AAC1D,SAAO,OAAO,UAAU;AAC1B;AAKO,SAAS,SAAS,OAAkD;AACzE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAKO,SAAS,QAAQ,OAAoC;AAC1D,SAAO,MAAM,QAAQ,KAAK;AAC5B;AAKO,SAAS,WAAW,OAA0D;AACnF,SAAO,OAAO,UAAU;AAC1B;AAKO,SAAS,OAAO,OAA+B;AACpD,SAAO,iBAAiB,QAAQ,CAAC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC/D;AAKO,SAAS,SAAS,OAAiC;AACxD,SAAO,iBAAiB;AAC1B;AAKO,SAAS,MAAM,OAAgD;AACpE,SAAO,iBAAiB;AAC1B;AAKO,SAAS,MAAM,OAAuC;AAC3D,SAAO,iBAAiB;AAC1B;AAKO,SAAS,UAAU,OAA2C;AACnE,SAAO,iBAAiB;AAC1B;AAKO,SAAS,OAAO,OAA+B;AACpD,SAAO,UAAU;AACnB;AAKO,SAAS,YAAY,OAAoC;AAC9D,SAAO,UAAU;AACnB;AAKO,SAAS,MAAM,OAA2C;AAC/D,SAAO,UAAU,QAAQ,UAAU;AACrC;AAMO,SAAS,QAAQ,OAAyB;AAC/C,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,WAAW;AACvD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,WAAW;AAClD,MAAI,iBAAiB,OAAO,iBAAiB,IAAK,QAAO,MAAM,SAAS;AACxE,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,KAAgC,EAAE,WAAW;AAC/F,SAAO;AACT;AAMO,SAAS,cAAiB,OAAU,SAAmD;AAC5F,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,UAAM,IAAI,MAAM,WAAW,8BAA8B;AAAA,EAC3D;AACF;AAKO,SAAS,WAAc,OAAgB,OAA+B,SAAsC;AACjH,MAAI,CAAC,MAAM,KAAK,GAAG;AACjB,UAAM,IAAI,MAAM,WAAW,oCAAoC;AAAA,EACjE;AACF;AAKO,SAAS,YAAe,OAAqB;AAClD,SAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAC9C;AAKO,SAAS,UAAa,OAAqB;AAChD,SAAO,YAAY,KAAK;AAC1B;AAQO,SAAS,QAAQ,OAAwB;AAC9C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,UAAW,QAAO;AACvC,MAAI,OAAO,UAAU,WAAY,QAAO;AACxC,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,OAAO,MAAM,KAAK,EAAG,QAAO;AAChC,QAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,iBAAiB,KAAM,QAAO;AAClC,MAAI,iBAAiB,OAAQ,QAAO;AACpC,MAAI,iBAAiB,IAAK,QAAO;AACjC,MAAI,iBAAiB,IAAK,QAAO;AACjC,MAAI,iBAAiB,QAAS,QAAO;AACrC,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "superjs-core",
3
- "version": "0.1.0",
4
- "description": "Zero-dependency JavaScript standard library — core, math, date, collection, string, async, io, & type utilities",
3
+ "version": "0.3.0",
4
+ "description": "Zero-dependency JavaScript standard library + dependency health scanner — core, math, date, collection, string, async, io, type, crypto, path & dep-exray",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
+ "bin": {
10
+ "dep-exray": "./dist/dep-exray/cli.js"
11
+ },
9
12
  "exports": {
10
13
  ".": {
11
14
  "import": "./dist/index.js",
@@ -50,6 +53,34 @@
50
53
  "./path": {
51
54
  "import": "./dist/path/index.js",
52
55
  "types": "./dist/path/index.d.ts"
56
+ },
57
+ "./dep-exray": {
58
+ "import": "./dist/dep-exray/index.js",
59
+ "types": "./dist/dep-exray/index.d.ts"
60
+ },
61
+ "./dep-exray/scanner": {
62
+ "import": "./dist/dep-exray/scanner/index.js",
63
+ "types": "./dist/dep-exray/scanner/index.d.ts"
64
+ },
65
+ "./dep-exray/analyzer": {
66
+ "import": "./dist/dep-exray/analyzer/index.js",
67
+ "types": "./dist/dep-exray/analyzer/index.d.ts"
68
+ },
69
+ "./dep-exray/reporter": {
70
+ "import": "./dist/dep-exray/reporter/index.js",
71
+ "types": "./dist/dep-exray/reporter/index.d.ts"
72
+ },
73
+ "./dep-exray/types": {
74
+ "import": "./dist/dep-exray/types.js",
75
+ "types": "./dist/dep-exray/types.d.ts"
76
+ },
77
+ "./dep-exray/known-mappings": {
78
+ "import": "./dist/dep-exray/known-mappings.js",
79
+ "types": "./dist/dep-exray/known-mappings.d.ts"
80
+ },
81
+ "./dep-exray/cli": {
82
+ "import": "./dist/dep-exray/cli.js",
83
+ "types": "./dist/dep-exray/cli.d.ts"
53
84
  }
54
85
  },
55
86
  "files": [
@@ -65,25 +96,34 @@
65
96
  "size": "size-limit",
66
97
  "bench": "vitest bench"
67
98
  },
99
+ "dependencies": {
100
+ "commander": "^12.0.0",
101
+ "picocolors": "^1.1.0"
102
+ },
68
103
  "devDependencies": {
69
104
  "@size-limit/file": "^11.0.0",
70
105
  "@types/node": "^26.0.1",
71
106
  "size-limit": "^11.0.0",
72
107
  "tsup": "^8.3.0",
73
108
  "typescript": "^5.7.0",
109
+ "vite": "^8.1.0",
74
110
  "vitest": "^2.1.0"
75
111
  },
76
112
  "size-limit": [
77
113
  {
78
114
  "path": "dist/index.js",
79
- "limit": "5 KB"
115
+ "limit": "10 KB"
80
116
  }
81
117
  ],
82
118
  "keywords": [
83
119
  "utilities",
84
120
  "standard-library",
85
121
  "typescript",
86
- "zero-dependency"
122
+ "zero-dependency",
123
+ "dependency-scanner",
124
+ "npm-audit",
125
+ "bloat-detection",
126
+ "security"
87
127
  ],
88
128
  "publishConfig": {
89
129
  "access": "public"