@visulima/package 5.0.13 → 5.0.14

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## @visulima/package [5.0.14](https://github.com/visulima/visulima/compare/%40visulima%2Fpackage%405.0.13...%40visulima%2Fpackage%405.0.14) (2026-08-17)
2
+
3
+
4
+ ### Dependencies
5
+
6
+ * **@visulima/fs:** upgraded to 6.0.1
7
+
1
8
  ## @visulima/package [5.0.13](https://github.com/visulima/visulima/compare/%40visulima%2Fpackage%405.0.12...%40visulima%2Fpackage%405.0.13) (2026-08-17)
2
9
 
3
10
  ## @visulima/package [5.0.12](https://github.com/visulima/visulima/compare/%40visulima%2Fpackage%405.0.11...%40visulima%2Fpackage%405.0.12) (2026-08-08)
package/dist/index.d.ts CHANGED
@@ -2,10 +2,11 @@ export { PackageNotFoundError } from "./error.js";
2
2
  export { type LockFileEntry, type LockFileIntegrity, type LockFileIntegrityAlgorithm, type LockFileParseResult, type LockFileType, decodeSriIntegrity, parseBunLockFile, parseLockFile, parseLockFileContent, parseLockFileSync, parseNpmLockFile, parsePnpmLockFile, parseYarnLockFile } from "./lockfile.js";
3
3
  export { type RootMonorepo, type Strategy, findMonorepoRoot, findMonorepoRootSync } from "./monorepo.js";
4
4
  export { findPackageRoot, findPackageRootSync } from "./package.js";
5
- export { type E as EnsurePackagesOptions, type F as FindPackageJsonCache, type N as NormalizedPackageJson, type a as NormalizedReadResult, type P as PackageJson, c as clearPackageJsonCache, e as ensurePackages, f as findPackageJson, b as findPackageJsonSync, g as getPackageJsonProperty, h as hasPackageJsonAnyDependency, d as hasPackageJsonProperty, p as parsePackageJson, i as parsePackageJsonSync, w as writePackageJson, j as writePackageJsonSync } from "./packem_shared/package-json.d-Ba7sjsO5.js";
5
+ export { type E as EnsurePackagesOptions, type F as FindPackageJsonCache, type N as NormalizedPackageJson, type a as NormalizedReadResult, type P as PackageJson, c as clearPackageJsonCache, e as ensurePackages, f as findPackageJson, b as findPackageJsonSync, g as getPackageJsonProperty, h as hasPackageJsonAnyDependency, d as hasPackageJsonProperty, p as parsePackageJson, i as parsePackageJsonSync, w as writePackageJson, j as writePackageJsonSync } from "./packem_shared/package-json.d-XOvCk6yp.js";
6
6
  export { type PackageManager, type PackageManagerResult, findLockFile, findLockFileSync, findPackageManager, findPackageManagerSync, generateMissingPackagesInstallMessage, getPackageManagerVersion, identifyInitiatingPackageManager } from "./package-manager.js";
7
7
  export { type PnpmCatalog, type PnpmCatalogs, isPackageInWorkspace, readPnpmCatalogs, readPnpmCatalogsSync, resolveCatalogReference, resolveCatalogReferences, resolveDependenciesCatalogReferences } from "./pnpm.js";
8
8
  import '@visulima/fs';
9
9
  import '@antfu/install-pkg';
10
10
  import 'normalize-package-data';
11
11
  import "./packem_shared/json-value.d-AIF0oxA6.js";
12
+ import 'tagged-tag';
@@ -1,5 +1,6 @@
1
1
  import '@visulima/fs';
2
- export { F as FindPackageJsonCache, a as NormalizedReadResult, c as clearPackageJsonCache, e as ensurePackages, f as findPackageJson, b as findPackageJsonSync, g as getPackageJsonProperty, h as hasPackageJsonAnyDependency, d as hasPackageJsonProperty, p as parsePackageJson, i as parsePackageJsonSync, w as writePackageJson, j as writePackageJsonSync } from "./packem_shared/package-json.d-Ba7sjsO5.js";
2
+ export { F as FindPackageJsonCache, a as NormalizedReadResult, c as clearPackageJsonCache, e as ensurePackages, f as findPackageJson, b as findPackageJsonSync, g as getPackageJsonProperty, h as hasPackageJsonAnyDependency, d as hasPackageJsonProperty, p as parsePackageJson, i as parsePackageJsonSync, w as writePackageJson, j as writePackageJsonSync } from "./packem_shared/package-json.d-XOvCk6yp.js";
3
3
  import "./packem_shared/json-value.d-AIF0oxA6.js";
4
4
  import '@antfu/install-pkg';
5
5
  import 'normalize-package-data';
6
+ import 'tagged-tag';
@@ -1,4 +1,4 @@
1
- import{createRequire as M}from"node:module";import{installPackage as q}from"@antfu/install-pkg";import{findUp as z,findUpSync as K,writeJson as V,writeJsonSync as X,readJson as G,readJsonSync as U,readFile as F,readFileSync as L}from"@visulima/fs";import{NotFoundError as P}from"@visulima/fs/error";import{toPath as x,parseJson as k}from"@visulima/fs/utils";import{readYaml as H,readYamlSync as Q}from"@visulima/fs/yaml";import{join as j}from"@visulima/path";import v from"json5";import Z from"normalize-package-data";import{readPnpmCatalogs as N,resolveCatalogReferences as p,readPnpmCatalogsSync as _}from"./pnpm.js";let B;const Y=r=>(B??=M(import.meta.url))(r),y=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,E=r=>{if(typeof y<"u"&&y.versions&&y.versions.node){const[e,t]=y.versions.node.split(".").map(Number);if(e>22||e===22&&t>=3||e===20&&t>=16)return y.getBuiltinModule(r)}return Y(r)},{existsSync:S}=E("node:fs"),{createInterface:ee}=E("node:readline"),{styleText:d}=E("node:util"),b=r=>{const e=typeof r;return r!==null&&(e==="object"||e==="function")},A=new Set(["__proto__","prototype","constructor"]),C=1e6,re=r=>r>="0"&&r<="9";function D(r){if(r==="0")return!0;if(/^[1-9]\d*$/.test(r)){const e=Number.parseInt(r,10);return e<=Number.MAX_SAFE_INTEGER&&e<=C}return!1}function $(r,e){return A.has(r)?!1:(r&&D(r)?e.push(Number.parseInt(r,10)):e.push(r),!0)}function ne(r){if(typeof r!="string")throw new TypeError(`Expected a string, got ${typeof r}`);const e=[];let t="",n="start",s=!1,o=0;for(const a of r){if(o++,s){t+=a,s=!1;continue}if(a==="\\"){if(n==="index")throw new Error(`Invalid character '${a}' in an index at position ${o}`);if(n==="indexEnd")throw new Error(`Invalid character '${a}' after an index at position ${o}`);s=!0,n=n==="start"?"property":n;continue}switch(a){case".":{if(n==="index")throw new Error(`Invalid character '${a}' in an index at position ${o}`);if(n==="indexEnd"){n="property";break}if(!$(t,e))return[];t="",n="property";break}case"[":{if(n==="index")throw new Error(`Invalid character '${a}' in an index at position ${o}`);if(n==="indexEnd"){n="index";break}if(n==="property"||n==="start"){if((t||n==="property")&&!$(t,e))return[];t=""}n="index";break}case"]":{if(n==="index"){if(t==="")t=(e.pop()||"")+"[]",n="property";else{const i=Number.parseInt(t,10);!Number.isNaN(i)&&Number.isFinite(i)&&i>=0&&i<=Number.MAX_SAFE_INTEGER&&i<=C&&t===String(i)?e.push(i):e.push(t),t="",n="indexEnd"}break}if(n==="indexEnd")throw new Error(`Invalid character '${a}' after an index at position ${o}`);t+=a;break}default:{if(n==="index"&&!re(a))throw new Error(`Invalid character '${a}' in an index at position ${o}`);if(n==="indexEnd")throw new Error(`Invalid character '${a}' after an index at position ${o}`);n==="start"&&(n="property"),t+=a}}}switch(s&&(t+="\\"),n){case"property":{if(!$(t,e))return[];break}case"index":throw new Error("Index was not closed");case"start":{e.push("");break}}return e}function I(r){if(typeof r=="string")return ne(r);if(Array.isArray(r)){const e=[];for(const[t,n]of r.entries()){if(typeof n!="string"&&typeof n!="number")throw new TypeError(`Expected a string or number for path segment at index ${t}, got ${typeof n}`);if(typeof n=="number"&&!Number.isFinite(n))throw new TypeError(`Path segment at index ${t} must be a finite number, got ${n}`);if(A.has(n))return[];typeof n=="string"&&D(n)?e.push(Number.parseInt(n,10)):e.push(n)}return e}return[]}function u(r,e,t){if(!b(r)||typeof e!="string"&&!Array.isArray(e))return t===void 0?r:t;const n=I(e);if(n.length===0)return t;for(let s=0;s<n.length;s++){const o=n[s];if(r=r[o],r==null){if(s!==n.length-1)return t;break}}return r===void 0?t:r}function te(r,e){if(!b(r)||typeof e!="string"&&!Array.isArray(e))return!1;const t=I(e);if(t.length===0)return!1;for(const n of t){if(!b(r)||!(n in r))return!1;r=r[n]}return!0}const se=async r=>{const{default:e=!1,message:t,transformer:n}=r,s=a=>{const i=d(["cyan","bold"],"?"),c=d(["bold"],a),l=e?`${d(["greenBright"],"Y")}${d(["gray"],"/n")}`:`y/${d(["yellowBright"],"N")}`;return`${i} ${c} ${d(["gray"],`(${l})`)}`},o=a=>n?n(a):a?d(["greenBright"],"Yes"):d(["yellowBright"],"No");return new Promise(a=>{const i=ee({input:process.stdin,output:process.stdout}),c=s(t);i.question(c,l=>{i.close();const f=l.trim().toLowerCase();if(f===""){a(e);return}if(f==="y"||f==="yes"){console.log(`${d(["greenBright"],"✓")} ${o(!0)}`),a(!0);return}if(f==="n"||f==="no"){console.log(`${d(["yellowBright"],"✗")} ${o(!1)}`),a(!1);return}console.log(`${d(["gray"],"→")} ${o(e)}`),a(e)}),i.on("SIGINT",()=>{i.close(),console.log(`
2
- ${d(["gray"],"→")} ${o(!1)}`),a(!1)})})},ae=typeof process.stdout<"u"&&!process.versions.deno&&!globalThis.window,J=/, ([^,]*)$/,g=new Map,m=new Map,h=(r,e={})=>{const t=e.strict&&e.ignoreWarnings?e.ignoreWarnings.map(String).toSorted((n,s)=>n.localeCompare(s)).join(","):"";return`${r}|s${String(e.strict?1:0)}|c${String(e.resolveCatalogs?1:0)}|j${String(e.json5===!1?0:1)}|y${String(e.yaml===!1?0:1)}|w${t}`},T=r=>r.trimStart().startsWith("{"),W=r=>{const e=`${r}|`;for(const t of[m,g])for(const n of t.keys())n.startsWith(e)&&t.delete(n)};class oe extends Error{constructor(e){super(`The following warnings were encountered while normalizing package data:
1
+ import{createRequire as M}from"node:module";import{installPackage as q}from"@antfu/install-pkg";import{findUp as K,findUpSync as z,writeJson as U,writeJsonSync as V,readJson as X,readJsonSync as G,readFile as L,readFileSync as F}from"@visulima/fs";import{NotFoundError as S}from"@visulima/fs/error";import{toPath as P,parseJson as j}from"@visulima/fs/utils";import{readYaml as H,readYamlSync as Q}from"@visulima/fs/yaml";import{join as v}from"@visulima/path";import D from"json5";import Z from"normalize-package-data";import{readPnpmCatalogs as _,resolveCatalogReferences as p,readPnpmCatalogsSync as C}from"./pnpm.js";let B;const Y=r=>(B??=M(import.meta.url))(r),y=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,E=r=>{if(typeof y<"u"&&y.versions&&y.versions.node){const[e,s]=y.versions.node.split(".").map(Number);if(e>22||e===22&&s>=3||e===20&&s>=16)return y.getBuiltinModule(r)}return Y(r)},{existsSync:k}=E("node:fs"),{createInterface:ee}=E("node:readline"),{styleText:d}=E("node:util"),x=r=>{const e=typeof r;return r!==null&&(e==="object"||e==="function")},m=new Set(["__proto__","prototype","constructor"]),re=Math.max(...[...m].map(r=>r.length)),A=1e6,ne=r=>r>="0"&&r<="9";function J(r){if(r==="0")return!0;if(/^[1-9]\d*$/.test(r)){const e=Number.parseInt(r,10);return e<=Number.MAX_SAFE_INTEGER&&e<=A}return!1}function b(r,e){return m.has(r)?!1:(r&&J(r)?e.push(Number.parseInt(r,10)):e.push(r),!0)}function te(r){if(typeof r!="string")throw new TypeError(`Expected a string, got ${typeof r}`);const e=[];let s="",n="",o=!1,t="start",c=!1,i=0;for(const a of r){if(i++,c){s+=a,c=!1;continue}if(a==="\\"){if(t==="index")throw new Error(`Invalid character '${a}' in an index at position ${i}`);if(t==="indexEnd")throw new Error(`Invalid character '${a}' after an index at position ${i}`);c=!0,t=t==="start"?"property":t;continue}switch(a){case".":{if(t==="index")throw new Error(`Invalid character '${a}' in an index at position ${i}`);if(t==="indexEnd"){t="property";break}if(!b(s,e))return[];s="",t="property";break}case"[":{if(t==="index")throw new Error(`Invalid character '${a}' in an index at position ${i}`);if(t==="indexEnd"){t="index";break}if(t==="property"&&s.length<=re&&m.has(s))return[];o=t==="property",t="index";break}case"]":{if(t==="indexEnd")throw new Error(`Invalid character '${a}' after an index at position ${i}`);if(t!=="index"){t==="start"&&(t="property"),s+=a;break}if(n===""){s+="[]",t="property";break}if((s!==""||o)&&!b(s,e))return[];s="",o=!1;const f=Number.parseInt(n,10),l=f<=A&&n===String(f);e.push(l?f:n),n="",t="indexEnd";break}default:{if(t==="index"){if(!ne(a))throw new Error(`Invalid character '${a}' in an index at position ${i}`);n+=a;break}if(t==="indexEnd")throw new Error(`Invalid character '${a}' after an index at position ${i}`);t==="start"&&(t="property"),s+=a}}}switch(c&&(s+="\\"),t){case"property":{if(!b(s,e))return[];break}case"index":throw new Error("Index was not closed");case"start":{e.push("");break}}return e}function N(r){if(typeof r=="string")return te(r);if(Array.isArray(r)){const e=[];for(const[s,n]of r.entries()){if(typeof n!="string"&&typeof n!="number")throw new TypeError(`Expected a string or number for path segment at index ${s}, got ${typeof n}`);if(typeof n=="number"&&!Number.isFinite(n))throw new TypeError(`Path segment at index ${s} must be a finite number, got ${n}`);if(m.has(n))return[];typeof n=="string"&&J(n)?e.push(Number.parseInt(n,10)):e.push(n)}return e}return[]}function u(r,e,s){if(!x(r)||typeof e!="string"&&!Array.isArray(e))return s===void 0?r:s;const n=N(e);if(n.length===0)return s;for(let o=0;o<n.length;o++){const t=n[o];if(r=r[t],r==null){if(o!==n.length-1)return s;break}}return r===void 0?s:r}function se(r,e){if(!x(r)||typeof e!="string"&&!Array.isArray(e))return!1;const s=N(e);if(s.length===0)return!1;for(const n of s){if(!x(r)||!(n in r))return!1;r=r[n]}return!0}const ae=async r=>{const{default:e=!1,message:s,transformer:n}=r,o=c=>{const i=d(["cyan","bold"],"?"),a=d(["bold"],c),f=e?`${d(["greenBright"],"Y")}${d(["gray"],"/n")}`:`y/${d(["yellowBright"],"N")}`;return`${i} ${a} ${d(["gray"],`(${f})`)}`},t=c=>n?n(c):c?d(["greenBright"],"Yes"):d(["yellowBright"],"No");return new Promise(c=>{const i=ee({input:process.stdin,output:process.stdout}),a=o(s);i.question(a,f=>{i.close();const l=f.trim().toLowerCase();if(l===""){c(e);return}if(l==="y"||l==="yes"){console.log(`${d(["greenBright"],"✓")} ${t(!0)}`),c(!0);return}if(l==="n"||l==="no"){console.log(`${d(["yellowBright"],"✗")} ${t(!1)}`),c(!1);return}console.log(`${d(["gray"],"→")} ${t(e)}`),c(e)}),i.on("SIGINT",()=>{i.close(),console.log(`
2
+ ${d(["gray"],"→")} ${t(!1)}`),c(!1)})})},oe=typeof process.stdout<"u"&&!process.versions.deno&&!globalThis.window,I=/, ([^,]*)$/,h=new Map,w=new Map,g=(r,e={})=>{const s=e.strict&&e.ignoreWarnings?e.ignoreWarnings.map(String).toSorted((n,o)=>n.localeCompare(o)).join(","):"";return`${r}|s${String(e.strict?1:0)}|c${String(e.resolveCatalogs?1:0)}|j${String(e.json5===!1?0:1)}|y${String(e.yaml===!1?0:1)}|w${s}`},T=r=>r.trimStart().startsWith("{"),W=r=>{const e=`${r}|`;for(const s of[w,h])for(const n of s.keys())n.startsWith(e)&&s.delete(n)};class ce extends Error{constructor(e){super(`The following warnings were encountered while normalizing package data:
3
3
  - ${e.join(`
4
- - `)}`),this.name="PackageJsonValidationError"}}const w=(r,e,t=[])=>{const n=[];if(Z(r,s=>{n.push(s)},e),e&&n.length>0){const s=n.filter(o=>!t.some(a=>a instanceof RegExp?a.test(o):a===o));if(s.length>0)throw new oe(s)}return r},ce=async r=>await H(r),ie=r=>Q(r),fe=async r=>{const e=await F(r);return v.parse(e)},le=r=>{const e=L(r);return v.parse(e)},O=async(r,e)=>e?.yaml!==!1&&(r.endsWith(".yaml")||r.endsWith(".yml"))?ce(r):e?.json5!==!1&&r.endsWith(".json5")?fe(r):G(r),R=(r,e)=>e?.yaml!==!1&&(r.endsWith(".yaml")||r.endsWith(".yml"))?ie(r):e?.json5!==!1&&r.endsWith(".json5")?le(r):U(r),Ee=async(r,e={})=>{const t={type:"file"};r&&(t.cwd=r);const n=["package.json"];e.yaml!==!1&&n.push("package.yaml","package.yml"),e.json5!==!1&&n.push("package.json5");const s=await z(n,t);if(!s)throw new P(`No such file or directory, for ${n.join(", ").replace(J," or $1")} found.`);const o=e.cache&&typeof e.cache!="boolean"?e.cache:m,a=h(s,e);if(e.cache&&o.has(a))return o.get(a);const i=await O(s,e);if(e.resolveCatalogs){const l=await N(s);l&&p(i,l)}w(i,e.strict??!1,e.ignoreWarnings);const c={packageJson:i,path:s};return e.cache&&o.set(a,c),c},xe=(r,e={})=>{const t={type:"file"};r&&(t.cwd=r);const n=["package.json"];e.yaml!==!1&&n.push("package.yaml","package.yml"),e.json5!==!1&&n.push("package.json5");const s=K(n,t);if(!s)throw new P(`No such file or directory, for ${n.join(", ").replace(J," or $1")} found.`);const o=e.cache&&typeof e.cache!="boolean"?e.cache:m,a=h(s,e);if(e.cache&&o.has(a))return o.get(a);const i=R(s,e);if(e.resolveCatalogs){const l=_(s);l&&p(i,l)}w(i,e.strict??!1,e.ignoreWarnings);const c={packageJson:i,path:s};return e.cache&&o.set(a,c),c},Se=async(r,e={})=>{const{cwd:t,...n}=e,s=x(t??process.cwd()),o=j(s,"package.json");await V(o,r,n),W(o)},Pe=(r,e={})=>{const{cwd:t,...n}=e,s=x(t??process.cwd()),o=j(s,"package.json");X(o,r,n),W(o)},ke=()=>{m.clear(),g.clear()},je=(r,e)=>{const t=typeof r=="object"&&!Array.isArray(r);if(!t&&!(typeof r=="string"))throw new TypeError("`packageFile` should be either an `object` or a `string`.");let s,o=!1,a;if(t)s=structuredClone(r);else if(!T(r)&&S(r)){a=r;const c=e?.cache&&typeof e.cache!="boolean"?e.cache:g,l=h(a,e);if(e?.cache&&c.has(l))return c.get(l);s=R(a,e),o=!0}else s=k(r);if(e?.resolveCatalogs)if(o){const c=_(r);c&&p(s,c)}else throw new Error("The 'resolveCatalogs' option can only be used on a file path.");w(s,e?.strict??!1,e?.ignoreWarnings);const i=s;return o&&e?.cache&&(typeof e.cache=="boolean"?g:e.cache).set(h(a,e),i),i},ve=async(r,e)=>{const t=typeof r=="object"&&!Array.isArray(r);if(!t&&!(typeof r=="string"))throw new TypeError("`packageFile` should be either an `object` or a `string`.");let s,o=!1,a;if(t)s=structuredClone(r);else if(!T(r)&&S(r)){a=r;const c=e?.cache&&typeof e.cache!="boolean"?e.cache:g,l=h(a,e);if(e?.cache&&c.has(l))return c.get(l);s=await O(a,e),o=!0}else s=k(r);if(e?.resolveCatalogs)if(o){const c=await N(r);c&&p(s,c)}else throw new Error("The 'resolveCatalogs' option can only be used on a file path.");w(s,e?.strict??!1,e?.ignoreWarnings);const i=s;return o&&e?.cache&&(typeof e.cache=="boolean"?g:e.cache).set(h(a,e),i),i},Ne=(r,e,t)=>u(r,e,t),_e=(r,e)=>te(r,e),Ae=(r,e,t)=>{const n=u(r,"dependencies",{}),s=u(r,"devDependencies",{}),o=u(r,"peerDependencies",{}),a={...n,...s,...t?.peerDeps===!1?{}:o};for(const i of e)if(Object.hasOwn(a,i))return!0;return!1},Ce=async(r,e,t="dependencies",n={})=>{const s=u(r,"dependencies",{}),o=u(r,"devDependencies",{}),a=u(r,"peerDependencies",{}),i=[],c={deps:!0,devDeps:!0,peerDeps:!1,...n,...n.confirm?{confirm:{...n.confirm}}:{}};for(const f of e)c.deps&&Object.hasOwn(s??{},f)||c.devDeps&&Object.hasOwn(o??{},f)||c.peerDeps&&Object.hasOwn(a??{},f)||i.push(f);if(i.length===0)return;if(process.env.CI||ae&&!process.stdout.isTTY){const f=`Skipping package installation for [${e.join(", ")}] because the process is not interactive.`;if(n.throwOnWarn)throw new Error(f);n.logger?.warn?n.logger.warn(f):console.warn(f);return}if(typeof c.confirm?.message=="function"&&(c.confirm.message=c.confirm.message(i)),c.confirm?.message===void 0){const f=`${i.length===1?"Package is":"Packages are"} required for this config: ${i.join(", ")}. Do you want to install them?`;c.confirm===void 0?c.confirm={message:f}:c.confirm.message=f}await se(c.confirm)&&await q(i,{...c.installPackage,cwd:c.cwd?x(c.cwd):void 0,dev:t==="devDependencies"})};export{ke as clearPackageJsonCache,Ce as ensurePackages,Ee as findPackageJson,xe as findPackageJsonSync,Ne as getPackageJsonProperty,Ae as hasPackageJsonAnyDependency,_e as hasPackageJsonProperty,ve as parsePackageJson,je as parsePackageJsonSync,Se as writePackageJson,Pe as writePackageJsonSync};
4
+ - `)}`),this.name="PackageJsonValidationError"}}const $=(r,e,s=[])=>{const n=[];if(Z(r,o=>{n.push(o)},e),e&&n.length>0){const o=n.filter(t=>!s.some(c=>c instanceof RegExp?c.test(t):c===t));if(o.length>0)throw new ce(o)}return r},ie=async r=>await H(r),fe=r=>Q(r),le=async r=>{const e=await L(r);return D.parse(e)},de=r=>{const e=F(r);return D.parse(e)},O=async(r,e)=>e?.yaml!==!1&&(r.endsWith(".yaml")||r.endsWith(".yml"))?ie(r):e?.json5!==!1&&r.endsWith(".json5")?le(r):X(r),R=(r,e)=>e?.yaml!==!1&&(r.endsWith(".yaml")||r.endsWith(".yml"))?fe(r):e?.json5!==!1&&r.endsWith(".json5")?de(r):G(r),Ee=async(r,e={})=>{const s={type:"file"};r&&(s.cwd=r);const n=["package.json"];e.yaml!==!1&&n.push("package.yaml","package.yml"),e.json5!==!1&&n.push("package.json5");const o=await K(n,s);if(!o)throw new S(`No such file or directory, for ${n.join(", ").replace(I," or $1")} found.`);const t=e.cache&&typeof e.cache!="boolean"?e.cache:w,c=g(o,e);if(e.cache&&t.has(c))return t.get(c);const i=await O(o,e);if(e.resolveCatalogs){const f=await _(o);f&&p(i,f)}$(i,e.strict??!1,e.ignoreWarnings);const a={packageJson:i,path:o};return e.cache&&t.set(c,a),a},Pe=(r,e={})=>{const s={type:"file"};r&&(s.cwd=r);const n=["package.json"];e.yaml!==!1&&n.push("package.yaml","package.yml"),e.json5!==!1&&n.push("package.json5");const o=z(n,s);if(!o)throw new S(`No such file or directory, for ${n.join(", ").replace(I," or $1")} found.`);const t=e.cache&&typeof e.cache!="boolean"?e.cache:w,c=g(o,e);if(e.cache&&t.has(c))return t.get(c);const i=R(o,e);if(e.resolveCatalogs){const f=C(o);f&&p(i,f)}$(i,e.strict??!1,e.ignoreWarnings);const a={packageJson:i,path:o};return e.cache&&t.set(c,a),a},ke=async(r,e={})=>{const{cwd:s,...n}=e,o=P(s??process.cwd()),t=v(o,"package.json");await U(t,r,n),W(t)},Se=(r,e={})=>{const{cwd:s,...n}=e,o=P(s??process.cwd()),t=v(o,"package.json");V(t,r,n),W(t)},je=()=>{w.clear(),h.clear()},ve=(r,e)=>{const s=typeof r=="object"&&!Array.isArray(r);if(!s&&!(typeof r=="string"))throw new TypeError("`packageFile` should be either an `object` or a `string`.");let o,t=!1,c;if(s)o=structuredClone(r);else if(!T(r)&&k(r)){c=r;const a=e?.cache&&typeof e.cache!="boolean"?e.cache:h,f=g(c,e);if(e?.cache&&a.has(f))return a.get(f);o=R(c,e),t=!0}else o=j(r);if(e?.resolveCatalogs)if(t){const a=C(r);a&&p(o,a)}else throw new Error("The 'resolveCatalogs' option can only be used on a file path.");$(o,e?.strict??!1,e?.ignoreWarnings);const i=o;return t&&e?.cache&&(typeof e.cache=="boolean"?h:e.cache).set(g(c,e),i),i},De=async(r,e)=>{const s=typeof r=="object"&&!Array.isArray(r);if(!s&&!(typeof r=="string"))throw new TypeError("`packageFile` should be either an `object` or a `string`.");let o,t=!1,c;if(s)o=structuredClone(r);else if(!T(r)&&k(r)){c=r;const a=e?.cache&&typeof e.cache!="boolean"?e.cache:h,f=g(c,e);if(e?.cache&&a.has(f))return a.get(f);o=await O(c,e),t=!0}else o=j(r);if(e?.resolveCatalogs)if(t){const a=await _(r);a&&p(o,a)}else throw new Error("The 'resolveCatalogs' option can only be used on a file path.");$(o,e?.strict??!1,e?.ignoreWarnings);const i=o;return t&&e?.cache&&(typeof e.cache=="boolean"?h:e.cache).set(g(c,e),i),i},_e=(r,e,s)=>u(r,e,s),Ce=(r,e)=>se(r,e),Ae=(r,e,s)=>{const n=u(r,"dependencies",{}),o=u(r,"devDependencies",{}),t=u(r,"peerDependencies",{}),c={...n,...o,...s?.peerDeps===!1?{}:t};for(const i of e)if(Object.hasOwn(c,i))return!0;return!1},Je=async(r,e,s="dependencies",n={})=>{const o=u(r,"dependencies",{}),t=u(r,"devDependencies",{}),c=u(r,"peerDependencies",{}),i=[],a={deps:!0,devDeps:!0,peerDeps:!1,...n,...n.confirm?{confirm:{...n.confirm}}:{}};for(const l of e)a.deps&&Object.hasOwn(o??{},l)||a.devDeps&&Object.hasOwn(t??{},l)||a.peerDeps&&Object.hasOwn(c??{},l)||i.push(l);if(i.length===0)return;if(process.env.CI||oe&&!process.stdout.isTTY){const l=`Skipping package installation for [${e.join(", ")}] because the process is not interactive.`;if(n.throwOnWarn)throw new Error(l);n.logger?.warn?n.logger.warn(l):console.warn(l);return}if(typeof a.confirm?.message=="function"&&(a.confirm.message=a.confirm.message(i)),a.confirm?.message===void 0){const l=`${i.length===1?"Package is":"Packages are"} required for this config: ${i.join(", ")}. Do you want to install them?`;a.confirm===void 0?a.confirm={message:l}:a.confirm.message=l}await ae(a.confirm)&&await q(i,{...a.installPackage,cwd:a.cwd?P(a.cwd):void 0,dev:s==="devDependencies"})};export{je as clearPackageJsonCache,Je as ensurePackages,Ee as findPackageJson,Pe as findPackageJsonSync,_e as getPackageJsonProperty,Ae as hasPackageJsonAnyDependency,Ce as hasPackageJsonProperty,De as parsePackageJson,ve as parsePackageJsonSync,ke as writePackageJson,Se as writePackageJsonSync};
@@ -2,6 +2,7 @@ import { WriteJsonOptions } from '@visulima/fs';
2
2
  import { InstallPackageOptions } from '@antfu/install-pkg';
3
3
  import { Package } from 'normalize-package-data';
4
4
  import { a as JsonValue, J as JsonObject } from "./json-value.d-AIF0oxA6.js";
5
+ import tag from 'tagged-tag';
5
6
  /**
6
7
  Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
7
8
 
@@ -363,16 +364,16 @@ An if-else-like type that resolves depending on whether the given type is `any`
363
364
 
364
365
  @example
365
366
  ```
366
- // When `T` is a NOT `any` or `never` (like `string`) => Returns `IfNotAnyOrNever` branch
367
- type A = IfNotAnyOrNever<string, 'VALID', 'IS_ANY', 'IS_NEVER'>;
367
+ // When `T` is neither `any` nor `never` (like `string`) => Returns `IfNot` branch
368
+ type A = IfNotAnyOrNever<string, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
368
369
  //=> 'VALID'
369
370
 
370
371
  // When `T` is `any` => Returns `IfAny` branch
371
- type B = IfNotAnyOrNever<any, 'VALID', 'IS_ANY', 'IS_NEVER'>;
372
+ type B = IfNotAnyOrNever<any, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
372
373
  //=> 'IS_ANY'
373
374
 
374
375
  // When `T` is `never` => Returns `IfNever` branch
375
- type C = IfNotAnyOrNever<never, 'VALID', 'IS_ANY', 'IS_NEVER'>;
376
+ type C = IfNotAnyOrNever<never, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
376
377
  //=> 'IS_NEVER'
377
378
  ```
378
379
 
@@ -385,7 +386,7 @@ import type {StringRepeat} from 'type-fest';
385
386
  type NineHundredNinetyNineSpaces = StringRepeat<' ', 999>;
386
387
 
387
388
  // The following implementation is not tail recursive
388
- type TrimLeft<S extends string> = IfNotAnyOrNever<S, S extends ` ${infer R}` ? TrimLeft<R> : S>;
389
+ type TrimLeft<S extends string> = IfNotAnyOrNever<S, {ifNot: S extends ` ${infer R}` ? TrimLeft<R> : S}>;
389
390
 
390
391
  // Hence, instantiations with long strings will fail
391
392
  // @ts-expect-error
@@ -394,7 +395,7 @@ type T1 = TrimLeft<NineHundredNinetyNineSpaces>;
394
395
  // Error: Type instantiation is excessively deep and possibly infinite.
395
396
 
396
397
  // To fix this, move the recursion into a helper type
397
- type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, _TrimLeftOptimised<S>>;
398
+ type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, {ifNot: _TrimLeftOptimised<S>}>;
398
399
 
399
400
  type _TrimLeftOptimised<S extends string> = S extends ` ${infer R}` ? _TrimLeftOptimised<R> : S;
400
401
 
@@ -402,7 +403,11 @@ type T2 = TrimLeftOptimised<NineHundredNinetyNineSpaces>;
402
403
  //=> ''
403
404
  ```
404
405
  */
405
- type IfNotAnyOrNever<T, IfNotAnyOrNever, IfAny = any, IfNever = never> = If<IsAny<T>, IfAny, If<IsNever<T>, IfNever, IfNotAnyOrNever>>;
406
+ type IfNotAnyOrNever<T, Cases extends {
407
+ ifNot: unknown;
408
+ ifAny?: unknown;
409
+ ifNever?: unknown;
410
+ }> = IsAny<T> extends true ? 'ifAny' extends keyof Cases ? Cases['ifAny'] : any : IsNever<T> extends true ? 'ifNever' extends keyof Cases ? Cases['ifNever'] : never : Cases['ifNot'];
406
411
  /**
407
412
  Indicates the value of `exactOptionalPropertyTypes` compiler option.
408
413
  */
@@ -438,7 +443,9 @@ type B = CollapseRestElement<[string?, string?, ...number[]]>;
438
443
  //=> [string | undefined, string | undefined, number]
439
444
  ```
440
445
  */
441
- type CollapseRestElement<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, _CollapseRestElement<TArray>>;
446
+ type CollapseRestElement<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, {
447
+ ifNot: _CollapseRestElement<TArray>;
448
+ }>;
442
449
  type _CollapseRestElement<TArray extends UnknownArray, ForwardAccumulator extends UnknownArray = [], BackwardAccumulator extends UnknownArray = []> = TArray extends UnknownArray // For distributing `TArray`
443
450
  ? keyof TArray & `${number}` extends never ?
444
451
  // Enters this branch, if `TArray` is empty (e.g., []),
@@ -501,242 +508,250 @@ type ShouldBeTrue = IsNegative<-1>;
501
508
  @category Numeric
502
509
  */
503
510
  type IsNegative<T extends _Numeric> = T extends Negative<T> ? true : false;
511
+ // eslint-disable-next-line type-fest/require-exported-types
512
+ type TagContainer<Token> = {
513
+ readonly [tag]: Token;
514
+ };
515
+ type Tag<Token extends PropertyKey, TagMetadata> = TagContainer<{ [K in Token]: TagMetadata; }>;
504
516
  /**
505
- Create a tuple type of the specified length with elements of the specified type.
517
+ Create a [tagged type](https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d) that can support [multiple tags](https://github.com/sindresorhus/type-fest/issues/665) and [per-tag metadata](https://medium.com/@ethanresnick/advanced-typescript-tagged-types-improved-with-type-level-metadata-5072fc125fcf).
506
518
 
507
- @example
508
- ```
509
- import type {TupleOf} from 'type-fest';
519
+ A type returned by `Tagged` can be passed to `Tagged` again, to create a type with multiple tags.
510
520
 
511
- type RGB = TupleOf<3, number>;
512
- //=> [number, number, number]
521
+ A tag's name is usually a string (and must be a string, number, or symbol), but each application of a tag can also contain an arbitrary type as its "metadata". See {@link GetTagMetadata} for examples and explanation.
513
522
 
514
- type Line = TupleOf<2, {x: number; y: number}>;
515
- //=> [{x: number; y: number}, {x: number; y: number}]
523
+ A type `A` returned by `Tagged` is assignable to another type `B` returned by `Tagged` if and only if:
524
+ - the underlying (untagged) type of `A` is assignable to the underlying type of `B`;
525
+ - `A` contains at least all the tags `B` has;
526
+ - and the metadata type for each of `A`'s tags is assignable to the metadata type of `B`'s corresponding tag.
516
527
 
517
- type TicTacToeBoard = TupleOf<3, TupleOf<3, 'X' | 'O' | null>>;
518
- //=> [['X' | 'O' | null, 'X' | 'O' | null, 'X' | 'O' | null], ['X' | 'O' | null, 'X' | 'O' | null, 'X' | 'O' | null], ['X' | 'O' | null, 'X' | 'O' | null, 'X' | 'O' | null]]
519
- ```
528
+ There have been several discussions about adding similar features to TypeScript. Unfortunately, nothing has (yet) moved forward:
529
+ - [Microsoft/TypeScript#202](https://github.com/microsoft/TypeScript/issues/202)
530
+ - [Microsoft/TypeScript#4895](https://github.com/microsoft/TypeScript/issues/4895)
531
+ - [Microsoft/TypeScript#33290](https://github.com/microsoft/TypeScript/pull/33290)
520
532
 
521
533
  @example
522
534
  ```
523
- import type {TupleOf} from 'type-fest';
535
+ import type {Tagged} from 'type-fest';
524
536
 
525
- type Range<Start extends number, End extends number> = Exclude<keyof TupleOf<End>, keyof TupleOf<Start>>;
537
+ type AccountNumber = Tagged<number, 'AccountNumber'>;
538
+ type AccountBalance = Tagged<number, 'AccountBalance'>;
526
539
 
527
- type ZeroToFour = Range<0, 5>;
528
- //=> '0' | '1' | '2' | '3' | '4'
540
+ function createAccountNumber(): AccountNumber {
541
+ // As you can see, casting from a `number` (the underlying type being tagged) is allowed.
542
+ return 2 as AccountNumber;
543
+ }
529
544
 
530
- type ThreeToEight = Range<3, 9>;
531
- //=> '3' | '4' | '5' | '6' | '7' | '8'
532
- ```
545
+ declare function getMoneyForAccount(accountNumber: AccountNumber): AccountBalance;
533
546
 
534
- Note: If the specified length is the non-literal `number` type, the result will not be a tuple but a regular array.
547
+ // This will compile successfully.
548
+ getMoneyForAccount(createAccountNumber());
535
549
 
536
- @example
537
- ```
538
- import type {TupleOf} from 'type-fest';
550
+ // But this won't, because it has to be explicitly passed as an `AccountNumber` type!
551
+ // Critically, you could not accidentally use an `AccountBalance` as an `AccountNumber`.
552
+ // @ts-expect-error
553
+ getMoneyForAccount(2);
539
554
 
540
- type StringArray = TupleOf<number, string>;
541
- //=> string[]
555
+ // You can also use tagged values like their underlying, untagged type.
556
+ // I.e., this will compile successfully because an `AccountNumber` can be used as a regular `number`.
557
+ // In this sense, the underlying base type is not hidden, which differentiates tagged types from opaque types in other languages.
558
+ const accountNumber = createAccountNumber() + 2;
542
559
  ```
543
560
 
544
- Note: If the type for elements is not specified, it will default to `unknown`.
545
-
546
561
  @example
547
562
  ```
548
- import type {TupleOf} from 'type-fest';
563
+ import type {Tagged} from 'type-fest';
549
564
 
550
- type UnknownTriplet = TupleOf<3>;
551
- //=> [unknown, unknown, unknown]
565
+ // You can apply multiple tags to a type by using `Tagged` repeatedly.
566
+ type Url = Tagged<string, 'URL'>;
567
+ type SpecialCacheKey = Tagged<Url, 'SpecialCacheKey'>;
568
+
569
+ // You can also pass a union of tag names, so this is equivalent to the above, although it doesn't give you the ability to assign distinct metadata to each tag.
570
+ type SpecialCacheKey2 = Tagged<string, 'URL' | 'SpecialCacheKey'>;
552
571
  ```
553
572
 
554
- Note: If the specified length is negative, the result will be an empty tuple.
573
+ @category Type
574
+ */
575
+ type Tagged<Type, TagName extends PropertyKey, TagMetadata = never> = Type & Tag<TagName, TagMetadata>;
576
+ /**
577
+ Get the untagged portion of a tagged type created with `Tagged`.
578
+
579
+ Why is this necessary?
580
+
581
+ 1. Use a `Tagged` type as object keys
582
+ 2. Prevent TS4058 error: "Return type of exported function has or is using name X from external module Y but cannot be named"
555
583
 
556
584
  @example
557
585
  ```
558
- import type {TupleOf} from 'type-fest';
586
+ import type {Tagged, UnwrapTagged} from 'type-fest';
559
587
 
560
- type EmptyTuple = TupleOf<-3, string>;
561
- //=> []
562
- ```
588
+ type AccountType = Tagged<'SAVINGS' | 'CHECKING', 'AccountType'>;
563
589
 
564
- Note: If the specified length has a decimal part, the decimal part will be ignored.
590
+ const moneyByAccountType: Record<UnwrapTagged<AccountType>, number> = {
591
+ SAVINGS: 99,
592
+ CHECKING: 0.1,
593
+ };
565
594
 
566
- @example
567
- ```
568
- import type {TupleOf} from 'type-fest';
595
+ // Without UnwrapTagged, the following expression would throw a type error.
596
+ const money = moneyByAccountType.SAVINGS; // TS error: Property 'SAVINGS' does not exist
569
597
 
570
- type DecimalLength = TupleOf<3.5, string>;
571
- //=> [string, string, string]
598
+ // Attempting to pass a non-Tagged type to UnwrapTagged will raise a type error.
599
+ // @ts-expect-error
600
+ type WontWork = UnwrapTagged<string>;
572
601
  ```
573
602
 
574
- Note: If you need a readonly tuple, simply wrap this type with `Readonly`, for example, to create `readonly [number, number, number]` use `Readonly<TupleOf<3, number>>`.
575
-
576
- @category Array
603
+ @category Type
577
604
  */
578
- type TupleOf<Length extends number, Fill = unknown> = IfNotAnyOrNever<Length, _TupleOf<If<IsNegative<Length>, 0, Length>, Fill>, Fill[], []>;
579
- type _TupleOf<Length extends number, Fill> = number extends Length ? Fill[] : BuildTupleDigitByDigit<`${Length}`, Fill>;
580
- type BuildTupleDigitByDigit<Length extends string, Fill, Accumulator extends UnknownArray = []> = Length extends `${infer First extends DigitCharacter}${infer Rest}` ? BuildTupleDigitByDigit<Rest, Fill, [...RepeatTupleTenTimes<Accumulator>, ...DigitTupleOf<First, Fill>]> : Accumulator;
581
- type RepeatTupleTenTimes<Tuple extends UnknownArray> = [...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple];
582
- type DigitTupleOf<Digit extends DigitCharacter, Fill> = [[], [Fill], [Fill, Fill], [Fill, Fill, Fill], [Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill, Fill, Fill, Fill, Fill]][Digit];
605
+ type UnwrapTagged<TaggedType extends Tag<PropertyKey, any>> = RemoveAllTags<TaggedType>;
606
+ type RemoveAllTags<T> = T extends Tag<PropertyKey, any> ? { [ThisTag in keyof T[typeof tag]]: T extends Tagged<infer Type, ThisTag, T[typeof tag][ThisTag]> ? RemoveAllTags<Type> : never; }[keyof T[typeof tag]] : T;
583
607
  /**
584
- Return a string representation of the given string or number.
608
+ Returns a boolean for whether the given type is a `string` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
585
609
 
586
- Note: This type is not the return type of the `.toString()` function.
587
- */
588
- type ToString<T> = T extends string | number ? `${T}` : never;
589
- /**
590
- Converts a numeric string to a number.
610
+ Useful for:
611
+ - providing strongly-typed string manipulation functions
612
+ - constraining strings to be a string literal
613
+ - type utilities, such as when constructing parsers and ASTs
614
+
615
+ The implementation of this type is inspired by the trick mentioned in this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
591
616
 
592
617
  @example
593
618
  ```
594
- type PositiveInt = StringToNumber<'1234'>;
595
- //=> 1234
619
+ import type {IsStringLiteral} from 'type-fest';
596
620
 
597
- type NegativeInt = StringToNumber<'-1234'>;
598
- //=> -1234
621
+ type CapitalizedString<T extends string> = IsStringLiteral<T> extends true ? Capitalize<T> : string;
599
622
 
600
- type PositiveFloat = StringToNumber<'1234.56'>;
601
- //=> 1234.56
602
-
603
- type NegativeFloat = StringToNumber<'-1234.56'>;
604
- //=> -1234.56
605
-
606
- type PositiveInfinity = StringToNumber<'Infinity'>;
607
- //=> Infinity
623
+ // https://github.com/yankeeinlondon/native-dash/blob/master/src/capitalize.ts
624
+ function capitalize<T extends Readonly<string>>(input: T): CapitalizedString<T> {
625
+ return (input.slice(0, 1).toUpperCase() + input.slice(1)) as CapitalizedString<T>;
626
+ }
608
627
 
609
- type NegativeInfinity = StringToNumber<'-Infinity'>;
610
- //=> -Infinity
628
+ const output = capitalize('hello, world!');
629
+ //=> 'Hello, world!'
611
630
  ```
612
631
 
613
- @category String
614
- @category Numeric
615
- @category Template literal
616
- */
617
- type StringToNumber<S extends string> = S extends `${infer N extends number}` ? N : S extends 'Infinity' ? PositiveInfinity : S extends '-Infinity' ? NegativeInfinity : never;
618
- /**
619
- Returns an array of the characters of the string.
620
-
621
632
  @example
622
633
  ```
623
- type A = StringToArray<'abcde'>;
624
- //=> ['a', 'b', 'c', 'd', 'e']
634
+ // String types with infinite set of possible values return `false`.
625
635
 
626
- type B = StringToArray<string>;
627
- //=> never
628
- ```
636
+ import type {IsStringLiteral} from 'type-fest';
629
637
 
630
- @category String
631
- */
632
- type StringToArray<S extends string, Result extends string[] = []> = string extends S ? never : S extends `${infer F}${infer R}` ? StringToArray<R, [...Result, F]> : Result;
633
- /**
634
- Returns the length of the given string.
638
+ type AllUppercaseStrings = IsStringLiteral<Uppercase<string>>;
639
+ //=> false
635
640
 
636
- @example
637
- ```
638
- type A = StringLength<'abcde'>;
639
- //=> 5
641
+ type StringsStartingWithOn = IsStringLiteral<`on${string}`>;
642
+ //=> false
640
643
 
641
- type B = StringLength<string>;
642
- //=> never
644
+ // This behaviour is particularly useful in string manipulation utilities, as infinite string types often require separate handling.
645
+
646
+ type Length<S extends string, Counter extends never[] = []> =
647
+ IsStringLiteral<S> extends false
648
+ ? number // return `number` for infinite string types
649
+ : S extends `${string}${infer Tail}`
650
+ ? Length<Tail, [...Counter, never]>
651
+ : Counter['length'];
652
+
653
+ type L1 = Length<Lowercase<string>>;
654
+ //=> number
655
+
656
+ type L2 = Length<`${number}`>;
657
+ //=> number
643
658
  ```
644
659
 
645
- @category String
646
- @category Template literal
660
+ @category Type Guard
661
+ @category Utilities
647
662
  */
648
- type StringLength<S extends string> = string extends S ? never : StringToArray<S>['length'];
663
+ type IsStringLiteral<S> = IfNotAnyOrNever<S, {
664
+ ifNot: _IsStringLiteral<CollapseLiterals<S extends TagContainer<any> ? UnwrapTagged<S> : S>>;
665
+ ifAny: false;
666
+ ifNever: false;
667
+ }>;
668
+ type _IsStringLiteral<S> =
669
+ // If `T` is an infinite string type (e.g., `on${string}`), `Record<T, never>` produces an index signature,
670
+ // and since `{}` extends index signatures, the result becomes `false`.
671
+ S extends string ? {} extends Record<S, never> ? false : true : false;
649
672
  /**
650
- Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both numeric strings and have the same length.
673
+ Create a tuple type of the specified length with elements of the specified type.
651
674
 
652
675
  @example
653
676
  ```
654
- type A = SameLengthPositiveNumericStringGt<'50', '10'>;
655
- //=> true
677
+ import type {TupleOf} from 'type-fest';
656
678
 
657
- type B = SameLengthPositiveNumericStringGt<'10', '10'>;
658
- //=> false
679
+ type RGB = TupleOf<3, number>;
680
+ //=> [number, number, number]
681
+
682
+ type Line = TupleOf<2, {x: number; y: number}>;
683
+ //=> [{x: number; y: number}, {x: number; y: number}]
684
+
685
+ type TicTacToeBoard = TupleOf<3, TupleOf<3, 'X' | 'O' | null>>;
686
+ //=> [['X' | 'O' | null, 'X' | 'O' | null, 'X' | 'O' | null], ['X' | 'O' | null, 'X' | 'O' | null, 'X' | 'O' | null], ['X' | 'O' | null, 'X' | 'O' | null, 'X' | 'O' | null]]
659
687
  ```
660
- */
661
- type SameLengthPositiveNumericStringGt<A extends string, B extends string> = A extends `${infer FirstA}${infer RestA}` ? B extends `${infer FirstB}${infer RestB}` ? FirstA extends FirstB ? SameLengthPositiveNumericStringGt<RestA, RestB> : PositiveNumericCharacterGt<FirstA, FirstB> : never : false;
662
- type NumericString = '0123456789';
663
- /**
664
- Returns a boolean for whether `A` is greater than `B`, where `A` and `B` are both positive numeric strings.
665
688
 
666
689
  @example
667
690
  ```
668
- type A = PositiveNumericStringGt<'500', '1'>;
669
- //=> true
691
+ import type {TupleOf} from 'type-fest';
670
692
 
671
- type B = PositiveNumericStringGt<'1', '1'>;
672
- //=> false
693
+ type Range<Start extends number, End extends number> = Exclude<keyof TupleOf<End>, keyof TupleOf<Start>>;
673
694
 
674
- type C = PositiveNumericStringGt<'1', '500'>;
675
- //=> false
695
+ type ZeroToFour = Range<0, 5>;
696
+ //=> '0' | '1' | '2' | '3' | '4'
697
+
698
+ type ThreeToEight = Range<3, 9>;
699
+ //=> '3' | '4' | '5' | '6' | '7' | '8'
676
700
  ```
677
- */
678
- type PositiveNumericStringGt<A extends string, B extends string> = A extends B ? false : [TupleOf<StringLength<A>, 0>, TupleOf<StringLength<B>, 0>] extends (infer R extends [readonly unknown[], readonly unknown[]]) ? R[0] extends [...R[1], ...infer Remain extends readonly unknown[]] ? 0 extends Remain['length'] ? SameLengthPositiveNumericStringGt<A, B> : true : false : never;
679
- /**
680
- Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both positive numeric characters.
701
+
702
+ Note: If the specified length is the non-literal `number` type, the result will not be a tuple but a regular array.
681
703
 
682
704
  @example
683
705
  ```
684
- type A = PositiveNumericCharacterGt<'5', '1'>;
685
- //=> true
706
+ import type {TupleOf} from 'type-fest';
686
707
 
687
- type B = PositiveNumericCharacterGt<'1', '1'>;
688
- //=> false
708
+ type StringArray = TupleOf<number, string>;
709
+ //=> string[]
689
710
  ```
690
- */
691
- type PositiveNumericCharacterGt<A extends string, B extends string> = NumericString extends `${infer HeadA}${A}${infer TailA}` ? NumericString extends `${infer HeadB}${B}${infer TailB}` ? HeadA extends `${HeadB}${infer _}${infer __}` ? true : false : never : never;
692
- /**
693
- Check whether the given type is a number or a number string.
694
711
 
695
- Supports floating-point as a string.
712
+ Note: If the type for elements is not specified, it will default to `unknown`.
696
713
 
697
714
  @example
698
715
  ```
699
- type A = IsNumberLike<'1'>;
700
- //=> true
716
+ import type {TupleOf} from 'type-fest';
701
717
 
702
- type B = IsNumberLike<'-1.1'>;
703
- //=> true
718
+ type UnknownTriplet = TupleOf<3>;
719
+ //=> [unknown, unknown, unknown]
720
+ ```
704
721
 
705
- type C = IsNumberLike<'5e-20'>;
706
- //=> true
722
+ Note: If the specified length is negative, the result will be an empty tuple.
707
723
 
708
- type D = IsNumberLike<1>;
709
- //=> true
724
+ @example
725
+ ```
726
+ import type {TupleOf} from 'type-fest';
710
727
 
711
- type E = IsNumberLike<'a'>;
712
- //=> false
713
- */
714
- type IsNumberLike<N> = IfNotAnyOrNever<N, N extends number | `${number}` ? true : false, boolean, false>;
715
- /**
716
- Returns the number with reversed sign.
728
+ type EmptyTuple = TupleOf<-3, string>;
729
+ //=> []
730
+ ```
731
+
732
+ Note: If the specified length has a decimal part, the decimal part will be ignored.
717
733
 
718
734
  @example
719
735
  ```
720
- type A = ReverseSign<-1>;
721
- //=> 1
736
+ import type {TupleOf} from 'type-fest';
722
737
 
723
- type B = ReverseSign<1>;
724
- //=> -1
738
+ type DecimalLength = TupleOf<3.5, string>;
739
+ //=> [string, string, string]
740
+ ```
725
741
 
726
- type C = ReverseSign<NegativeInfinity>;
727
- //=> PositiveInfinity
742
+ Note: If you need a readonly tuple, simply wrap this type with `Readonly`, for example, to create `readonly [number, number, number]` use `Readonly<TupleOf<3, number>>`.
728
743
 
729
- type D = ReverseSign<PositiveInfinity>;
730
- //=> NegativeInfinity
731
- ```
744
+ @category Array
732
745
  */
733
- type ReverseSign<N extends number> =
734
- // Handle edge cases
735
- N extends 0 ? 0 : N extends PositiveInfinity ? NegativeInfinity : N extends NegativeInfinity ? PositiveInfinity :
736
- // Handle negative numbers
737
- `${N}` extends `-${infer P extends number}` ? P :
738
- // Handle positive numbers
739
- `-${N}` extends `${infer R extends number}` ? R : never;
746
+ type TupleOf<Length extends number, Fill = unknown> = IfNotAnyOrNever<Length, {
747
+ ifNot: _TupleOf<If<IsNegative<Length>, 0, Length>, Fill>;
748
+ ifAny: Fill[];
749
+ ifNever: [];
750
+ }>;
751
+ type _TupleOf<Length extends number, Fill> = number extends Length ? Fill[] : BuildTupleDigitByDigit<`${Length}`, Fill>;
752
+ type BuildTupleDigitByDigit<Length extends string, Fill, Accumulator extends UnknownArray = []> = Length extends `${infer First extends DigitCharacter}${infer Rest}` ? BuildTupleDigitByDigit<Rest, Fill, [...RepeatTupleTenTimes<Accumulator>, ...DigitTupleOf<First, Fill>]> : Accumulator;
753
+ type RepeatTupleTenTimes<Tuple extends UnknownArray> = [...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple, ...Tuple];
754
+ type DigitTupleOf<Digit extends DigitCharacter, Fill> = [[], [Fill], [Fill, Fill], [Fill, Fill, Fill], [Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill, Fill, Fill, Fill], [Fill, Fill, Fill, Fill, Fill, Fill, Fill, Fill, Fill]][Digit];
740
755
  /**
741
756
  Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
742
757
 
@@ -1033,6 +1048,57 @@ type Merge<Destination, Source> = Destination extends unknown // For distributin
1033
1048
  : never; // Should never happen
1034
1049
  type _Merge<Destination, Source> = Simplify<SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>> & SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>>;
1035
1050
  /**
1051
+ Converts a numeric string to a number.
1052
+
1053
+ @example
1054
+ ```
1055
+ import type {StringToNumber} from 'type-fest';
1056
+
1057
+ type PositiveInteger = StringToNumber<'1234'>;
1058
+ //=> 1234
1059
+
1060
+ type NegativeInteger = StringToNumber<'-1234'>;
1061
+ //=> -1234
1062
+
1063
+ type PositiveFloat = StringToNumber<'1234.56'>;
1064
+ //=> 1234.56
1065
+
1066
+ type NegativeFloat = StringToNumber<'-1234.56'>;
1067
+ //=> -1234.56
1068
+
1069
+ type PositiveInfinity = StringToNumber<'Infinity'>;
1070
+ //=> Infinity
1071
+
1072
+ type NegativeInfinity = StringToNumber<'-Infinity'>;
1073
+ //=> -Infinity
1074
+ ```
1075
+
1076
+ Note: Some strings, such as `'1.50'`, `'0b10'`, or `'12_345'`, may look like they can be converted to numbers, but they don't actually have corresponding numeric literals. So, in such cases, this type produces `never`. See [type-fest#1446](https://github.com/sindresorhus/type-fest/pull/1446) for more details.
1077
+
1078
+ @example
1079
+ ```
1080
+ import type {StringToNumber} from 'type-fest';
1081
+
1082
+ type FractionalsEndingInZero = StringToNumber<'1.50'>;
1083
+ //=> never
1084
+
1085
+ type NonDecimalBases = StringToNumber<'0b10' | '0o10' | '0x10'>;
1086
+ //=> never
1087
+
1088
+ type NumericSeparators = StringToNumber<'12_345'>;
1089
+ //=> never
1090
+ ```
1091
+
1092
+ @category String
1093
+ @category Numeric
1094
+ @category Template literal
1095
+ */
1096
+ type StringToNumber<S extends string> = IfNotAnyOrNever<S, {
1097
+ ifNot: _StringToNumber<S>;
1098
+ ifAny: number;
1099
+ }>;
1100
+ type _StringToNumber<S extends string> = S extends `${infer N extends number}` ? number extends N ? `${number}` extends S ? N : never : N : string extends S ? number : S extends 'Infinity' ? PositiveInfinity : S extends '-Infinity' ? NegativeInfinity : never;
1101
+ /**
1036
1102
  Merges user specified options with default options.
1037
1103
 
1038
1104
  @example
@@ -1088,6 +1154,34 @@ type ApplyDefaultOptions<Options extends object, Defaults extends Simplify<Omit<
1088
1154
  ) ? Result : never;
1089
1155
  type _ApplyDefaultOptions<Options, Defaults, SpecifiedOptions> = If<IsAny<SpecifiedOptions>, Defaults, If<IsNever<SpecifiedOptions>, Defaults, Merge<Defaults, { [Key in keyof SpecifiedOptions as undefined extends Required<Options>[Key & keyof Options] ? Key : undefined extends SpecifiedOptions[Key] ? never : Key]: SpecifiedOptions[Key]; }>>>;
1090
1156
  /**
1157
+ Collapses literal types in a union into their corresponding primitive types, when possible. For example, `CollapseLiterals<'foo' | 'bar' | (string & {})>` returns `string`.
1158
+
1159
+ Note: This doesn't collapse literals within tagged types. For example, `CollapseLiterals<Tagged<'foo' | (string & {}), 'Tag'>>` returns `("foo" & Tag<"Tag", never>) | (string & Tag<"Tag", never>)` and not `string & Tag<"Tag", never>`.
1160
+
1161
+ Use-case: For collapsing unions created using {@link LiteralUnion}.
1162
+
1163
+ @example
1164
+ ```
1165
+ import type {LiteralUnion} from 'type-fest';
1166
+
1167
+ type A = CollapseLiterals<'foo' | 'bar' | (string & {})>;
1168
+ //=> string
1169
+
1170
+ type B = CollapseLiterals<LiteralUnion<1 | 2 | 3, number>>;
1171
+ //=> number
1172
+
1173
+ type C = CollapseLiterals<LiteralUnion<'onClick' | 'onChange', `on${string}`>>;
1174
+ //=> `on${string}`
1175
+
1176
+ type D = CollapseLiterals<'click' | 'change' | (`on${string}` & {})>;
1177
+ //=> 'click' | 'change' | `on${string}`
1178
+
1179
+ type E = CollapseLiterals<LiteralUnion<'foo' | 'bar', string> | null | undefined>;
1180
+ //=> string | null | undefined
1181
+ ```
1182
+ */
1183
+ type CollapseLiterals<T> = {} extends T ? T : T extends (infer U) & {} ? U : T;
1184
+ /**
1091
1185
  @see {@link SomeExtend}
1092
1186
  */
1093
1187
  type SomeExtendOptions = {
@@ -1174,9 +1268,13 @@ type B = SomeExtend<[1?, 2?, '3'?], string | undefined>;
1174
1268
  @category Array
1175
1269
  */
1176
1270
  type SomeExtend<TArray extends UnknownArray, Type, Options extends SomeExtendOptions = {}> = _SomeExtend<CollapseRestElement<TArray>, Type, ApplyDefaultOptions<SomeExtendOptions, DefaultSomeExtendOptions, Options>>;
1177
- type _SomeExtend<TArray extends UnknownArray, Type, Options extends Required<SomeExtendOptions>> = IfNotAnyOrNever<TArray, TArray extends readonly [infer First, ...infer Rest] ? IsNever<First> extends true ? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true ?
1178
- // If target `Type` is also `never`, or is `any`, or `strictNever` is disabled, return `true`.
1179
- true : _SomeExtend<Rest, Type, Options> : First extends Type ? true : _SomeExtend<Rest, Type, Options> : false, false, false>;
1271
+ type _SomeExtend<TArray extends UnknownArray, Type, Options extends Required<SomeExtendOptions>> = IfNotAnyOrNever<TArray, {
1272
+ ifNot: TArray extends readonly [infer First, ...infer Rest] ? IsNever<First> extends true ? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true ?
1273
+ // If target `Type` is also `never`, or is `any`, or `strictNever` is disabled, return `true`.
1274
+ true : _SomeExtend<Rest, Type, Options> : First extends Type ? true : _SomeExtend<Rest, Type, Options> : false;
1275
+ ifAny: false;
1276
+ ifNever: false;
1277
+ }>;
1180
1278
  /**
1181
1279
  Returns a boolean for whether any of the given elements is `true`.
1182
1280
 
@@ -1325,6 +1423,215 @@ type G = Or<never, never>;
1325
1423
  */
1326
1424
  type Or<A extends boolean, B extends boolean> = OrAll<[A, B]>;
1327
1425
  /**
1426
+ @see {@link StringToArray}
1427
+ */
1428
+ type StringToArrayOptions = {
1429
+ /**
1430
+ When enabled, non-literal parts of the string (e.g., `string`, `Uppercase<string>`) are mapped as single elements instead of being mapped as a rest element.
1431
+
1432
+ Note: Enabling this option can produce misleading results that might not reflect the actual runtime behavior.
1433
+ For example, `StringToArray<string, {mapNonLiteralsDirectly: true}>` returns `[string]`, but at runtime, the string could be `'abc'` (which satisfies `string`), and converting it to an array would result in `['a', 'b', 'c']`, which doesn't satisfy `[string]`.
1434
+
1435
+ So, it is recommended to not enable this option unless you are aware of the implications.
1436
+
1437
+ @default false
1438
+
1439
+ @example
1440
+ ```
1441
+ import type {StringToArray} from 'type-fest';
1442
+
1443
+ type A = StringToArray<string, {mapNonLiteralsDirectly: false}>;
1444
+ //=> string[]
1445
+
1446
+ type B = StringToArray<string, {mapNonLiteralsDirectly: true}>;
1447
+ //=> [string]
1448
+
1449
+ type C = StringToArray<`on${string}`, {mapNonLiteralsDirectly: false}>;
1450
+ //=> ['o', 'n', ...string[]]
1451
+
1452
+ type D = StringToArray<`on${string}`, {mapNonLiteralsDirectly: true}>;
1453
+ //=> ['o', 'n', string]
1454
+
1455
+ type E = StringToArray<`${string}xyz`, {mapNonLiteralsDirectly: false}>;
1456
+ //=> [...string[], 'x', 'y', 'z']
1457
+
1458
+ type F = StringToArray<`${string}xyz`, {mapNonLiteralsDirectly: true}>;
1459
+ //=> [string, 'x', 'y', 'z']
1460
+ ```
1461
+ */
1462
+ mapNonLiteralsDirectly?: boolean;
1463
+ };
1464
+ type DefaultStringToArrayOptions = {
1465
+ mapNonLiteralsDirectly: false;
1466
+ };
1467
+ /**
1468
+ Returns an array of the characters of the specified string.
1469
+
1470
+ @example
1471
+ ```
1472
+ import type {StringToArray} from 'type-fest';
1473
+
1474
+ type A = StringToArray<'abcde'>;
1475
+ //=> ['a', 'b', 'c', 'd', 'e']
1476
+
1477
+ type B = StringToArray<''>;
1478
+ //=> []
1479
+
1480
+ type C = StringToArray<string>;
1481
+ //=> string[]
1482
+
1483
+ type D = StringToArray<`foo${string}bar`>;
1484
+ //=> ['f', 'o', 'o', ...string[], 'b', 'a', 'r']
1485
+
1486
+ type E = StringToArray<`foo${string}bar`, {mapNonLiteralsDirectly: true}>;
1487
+ //=> ['f', 'o', 'o', string, 'b', 'a', 'r']
1488
+ ```
1489
+
1490
+ @see {@link StringToArrayOptions}
1491
+
1492
+ @category String
1493
+ */
1494
+ type StringToArray<S extends string, Options extends StringToArrayOptions = {}> = IfNotAnyOrNever<S, {
1495
+ ifNot: _StringToArray<S, ApplyDefaultOptions<StringToArrayOptions, DefaultStringToArrayOptions, Options>>;
1496
+ ifAny: unknown[];
1497
+ }>;
1498
+ type _StringToArray<S extends string, Options extends Required<StringToArrayOptions>, Accumulator extends string[] = []> = S extends `${infer First}${infer Rest}` ? Or<IsStringLiteral<First>, Options['mapNonLiteralsDirectly']> extends true ? _StringToArray<Rest, Options, [...Accumulator, First]> : _StringToArray<Rest, Options, [...Accumulator, ...First[]]> : S extends '' ? Accumulator : Options['mapNonLiteralsDirectly'] extends true ? [...Accumulator, S] : [...Accumulator, ...S[]];
1499
+ /**
1500
+ Returns the length of the given string.
1501
+
1502
+ @example
1503
+ ```
1504
+ import type {StringLength} from 'type-fest';
1505
+
1506
+ type A = StringLength<'abcde'>;
1507
+ //=> 5
1508
+
1509
+ type B = StringLength<'abcde' | 'fgh'>;
1510
+ //=> 3 | 5
1511
+ ```
1512
+
1513
+ For non-literal strings, the result is `number` because the length of a non-literal string can be any number.
1514
+
1515
+ @example
1516
+ ```
1517
+ import type {StringLength} from 'type-fest';
1518
+
1519
+ type A = StringLength<string>;
1520
+ //=> number
1521
+
1522
+ type B = StringLength<Uppercase<string>>;
1523
+ //=> number
1524
+
1525
+ type C = StringLength<`${string}abc`>;
1526
+ //=> number
1527
+ ```
1528
+
1529
+ @category String
1530
+ @category Template literal
1531
+ */
1532
+ type StringLength<S extends string> = StringToArray<S>['length'];
1533
+ /**
1534
+ Return a string representation of the given string or number.
1535
+
1536
+ Note: This type is not the return type of the `.toString()` function.
1537
+ */
1538
+ type ToString<T> = T extends string | number ? `${T}` : never;
1539
+ /**
1540
+ Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both numeric strings and have the same length.
1541
+
1542
+ @example
1543
+ ```
1544
+ type A = SameLengthPositiveNumericStringGt<'50', '10'>;
1545
+ //=> true
1546
+
1547
+ type B = SameLengthPositiveNumericStringGt<'10', '10'>;
1548
+ //=> false
1549
+ ```
1550
+ */
1551
+ type SameLengthPositiveNumericStringGt<A extends string, B extends string> = A extends `${infer FirstA}${infer RestA}` ? B extends `${infer FirstB}${infer RestB}` ? FirstA extends FirstB ? SameLengthPositiveNumericStringGt<RestA, RestB> : PositiveNumericCharacterGt<FirstA, FirstB> : never : false;
1552
+ type NumericString = '0123456789';
1553
+ /**
1554
+ Returns a boolean for whether `A` is greater than `B`, where `A` and `B` are both positive numeric strings.
1555
+
1556
+ @example
1557
+ ```
1558
+ type A = PositiveNumericStringGt<'500', '1'>;
1559
+ //=> true
1560
+
1561
+ type B = PositiveNumericStringGt<'1', '1'>;
1562
+ //=> false
1563
+
1564
+ type C = PositiveNumericStringGt<'1', '500'>;
1565
+ //=> false
1566
+ ```
1567
+ */
1568
+ type PositiveNumericStringGt<A extends string, B extends string> = A extends B ? false : [TupleOf<StringLength<A>, 0>, TupleOf<StringLength<B>, 0>] extends (infer R extends [readonly unknown[], readonly unknown[]]) ? R[0] extends [...R[1], ...infer Remain extends readonly unknown[]] ? 0 extends Remain['length'] ? SameLengthPositiveNumericStringGt<A, B> : true : false : never;
1569
+ /**
1570
+ Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both positive numeric characters.
1571
+
1572
+ @example
1573
+ ```
1574
+ type A = PositiveNumericCharacterGt<'5', '1'>;
1575
+ //=> true
1576
+
1577
+ type B = PositiveNumericCharacterGt<'1', '1'>;
1578
+ //=> false
1579
+ ```
1580
+ */
1581
+ type PositiveNumericCharacterGt<A extends string, B extends string> = NumericString extends `${infer HeadA}${A}${infer TailA}` ? NumericString extends `${infer HeadB}${B}${infer TailB}` ? HeadA extends `${HeadB}${infer _}${infer __}` ? true : false : never : never;
1582
+ /**
1583
+ Check whether the given type is a number or a number string.
1584
+
1585
+ Supports floating-point as a string.
1586
+
1587
+ @example
1588
+ ```
1589
+ type A = IsNumberLike<'1'>;
1590
+ //=> true
1591
+
1592
+ type B = IsNumberLike<'-1.1'>;
1593
+ //=> true
1594
+
1595
+ type C = IsNumberLike<'5e-20'>;
1596
+ //=> true
1597
+
1598
+ type D = IsNumberLike<1>;
1599
+ //=> true
1600
+
1601
+ type E = IsNumberLike<'a'>;
1602
+ //=> false
1603
+ */
1604
+ type IsNumberLike<N> = IfNotAnyOrNever<N, {
1605
+ ifNot: N extends number | `${number}` ? true : false;
1606
+ ifAny: boolean;
1607
+ ifNever: false;
1608
+ }>;
1609
+ /**
1610
+ Returns the number with reversed sign.
1611
+
1612
+ @example
1613
+ ```
1614
+ type A = ReverseSign<-1>;
1615
+ //=> 1
1616
+
1617
+ type B = ReverseSign<1>;
1618
+ //=> -1
1619
+
1620
+ type C = ReverseSign<NegativeInfinity>;
1621
+ //=> PositiveInfinity
1622
+
1623
+ type D = ReverseSign<PositiveInfinity>;
1624
+ //=> NegativeInfinity
1625
+ ```
1626
+ */
1627
+ type ReverseSign<N extends number> =
1628
+ // Handle edge cases
1629
+ N extends 0 ? 0 : N extends PositiveInfinity ? NegativeInfinity : N extends NegativeInfinity ? PositiveInfinity :
1630
+ // Handle negative numbers
1631
+ `${N}` extends `-${infer P extends number}` ? P :
1632
+ // Handle positive numbers
1633
+ `-${N}` extends `${infer R extends number}` ? R : never;
1634
+ /**
1328
1635
  @see {@link AllExtend}
1329
1636
  */
1330
1637
  type AllExtendOptions = {
@@ -1417,9 +1724,13 @@ type B = AllExtend<[1?, 2?, 3?], number | undefined>;
1417
1724
  @category Array
1418
1725
  */
1419
1726
  type AllExtend<TArray extends UnknownArray, Type, Options extends AllExtendOptions = {}> = _AllExtend<CollapseRestElement<TArray>, Type, ApplyDefaultOptions<AllExtendOptions, DefaultAllExtendOptions, Options>>;
1420
- type _AllExtend<TArray extends UnknownArray, Type, Options extends Required<AllExtendOptions>> = IfNotAnyOrNever<TArray, TArray extends readonly [infer First, ...infer Rest] ? IsNever<First> extends true ? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true ?
1421
- // If target `Type` is also `never`, or is `any`, or `strictNever` is disabled, recurse further.
1422
- _AllExtend<Rest, Type, Options> : false : First extends Type ? _AllExtend<Rest, Type, Options> : false : true, false, false>;
1727
+ type _AllExtend<TArray extends UnknownArray, Type, Options extends Required<AllExtendOptions>> = IfNotAnyOrNever<TArray, {
1728
+ ifNot: TArray extends readonly [infer First, ...infer Rest] ? IsNever<First> extends true ? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true ?
1729
+ // If target `Type` is also `never`, or is `any`, or `strictNever` is disabled, recurse further.
1730
+ _AllExtend<Rest, Type, Options> : false : First extends Type ? _AllExtend<Rest, Type, Options> : false : true;
1731
+ ifAny: false;
1732
+ ifNever: false;
1733
+ }>;
1423
1734
  /**
1424
1735
  Returns a boolean for whether all of the given elements are `true`.
1425
1736
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visulima/package",
3
- "version": "5.0.13",
3
+ "version": "5.0.14",
4
4
  "description": "A comprehensive package management utility that helps you find root directories, monorepos, package managers, and parse package.json, package.yaml, and package.json5 files with advanced features like catalog resolution.",
5
5
  "keywords": [
6
6
  "anolilab",
@@ -99,8 +99,8 @@
99
99
  "MIGRATION-GUIDE.md"
100
100
  ],
101
101
  "dependencies": {
102
- "@antfu/install-pkg": "^1.1.0",
103
- "@visulima/fs": "6.0.0",
102
+ "@antfu/install-pkg": "^2.0.1",
103
+ "@visulima/fs": "6.0.1",
104
104
  "@visulima/path": "4.0.0",
105
105
  "json5": "^2.2.3",
106
106
  "normalize-package-data": "^9.0.0",