@flex-development/mlly 1.0.0-beta.5 → 1.0.0-beta.6

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,17 @@
1
+ ## [1.0.0-beta.6](https://github.com/flex-development/mlly/compare/1.0.0-beta.5...1.0.0-beta.6) (2026-02-12)
2
+
3
+ ### ⚠ BREAKING CHANGES
4
+
5
+ - **lib:** [`resolveModule`] support extension rewrite map
6
+
7
+ ### :package: Build
8
+
9
+ - [[`38c36b4`](https://github.com/flex-development/mlly/commit/38c36b4a6df62494e87aeb6ba7d9ce8466ab22cc)] **deps-dev:** Bump vite-tsconfig-paths from 6.1.0 to 6.1.1 ([#975](https://github.com/flex-development/mlly/issues/975))
10
+
11
+ ### :sparkles: Features
12
+
13
+ - [[`efdcc40`](https://github.com/flex-development/mlly/commit/efdcc40de2380932f7cfac80b0d7e96a2cdb8e48)] **lib:** [`resolveModule`] support extension rewrite map
14
+
1
15
  ## [1.0.0-beta.5](https://github.com/flex-development/mlly/compare/1.0.0-beta.4...1.0.0-beta.5) (2026-02-12)
2
16
 
3
17
  ### :package: Build
@@ -1312,3 +1326,4 @@
1312
1326
 
1313
1327
 
1314
1328
 
1329
+
package/README.md CHANGED
@@ -23,6 +23,7 @@
23
23
  - [Resolve like Node.js](#resolve-like-nodejs)
24
24
  - [Resolve with custom conditions](#resolve-with-custom-conditions)
25
25
  - [Resolve a directory index](#resolve-a-directory-index)
26
+ - [Resolve path aliases](#resolve-path-aliases)
26
27
  - [Rewrite an extension](#rewrite-an-extension)
27
28
  - [Use a custom file system](#use-a-custom-file-system)
28
29
  - [Use Cases](#use-cases)
@@ -67,7 +68,6 @@
67
68
  - [`Awaitable<T>`](#awaitablet)
68
69
  - [`BufferEncodingMap`](#bufferencodingmap)
69
70
  - [`BufferEncoding`](#bufferencoding)
70
- - [`ChangeExtFn<[Ext]>`](#changeextfnext)
71
71
  - [`ConditionMap`](#conditionmap)
72
72
  - [`Condition`](#condition)
73
73
  - [`Dot`](#dot)
@@ -75,8 +75,10 @@
75
75
  - [`EmptyObject`](#emptyobject)
76
76
  - [`EmptyString`](#emptystring)
77
77
  - [`Ext`](#ext)
78
+ - [`ExtensionRewrites`](#extensionrewrites)
78
79
  - [`FileContent`](#filecontent)
79
80
  - [`FileSystem`](#filesystem)
81
+ - [`GetNewExtension<[T]>`](#getnewextensiont)
80
82
  - [`GetSourceContext`](#getsourcecontext)
81
83
  - [`GetSourceHandler`](#getsourcehandler)
82
84
  - [`GetSourceHandlers`](#getsourcehandlers)
@@ -215,6 +217,39 @@ const resolved: URL = resolveModule('./src/lib', import.meta.url, {
215
217
  })
216
218
  ```
217
219
 
220
+ ### Resolve path aliases
221
+
222
+ ```ts
223
+ import { resolveModule, type Aliases } from '@flex-development/mlly'
224
+
225
+ /**
226
+ * The path mappings dictionary.
227
+ *
228
+ * @const {Aliases} aliases
229
+ */
230
+ const aliases: Aliases = {
231
+ '@/internal': './src/internal',
232
+ '@/internal/*': './src/internal/*'
233
+ }
234
+
235
+ /**
236
+ * The resolved directory URL.
237
+ *
238
+ * @const {URL} directory
239
+ */
240
+ const directory: URL = resolveModule('@/internal', import.meta.url, { aliases })
241
+
242
+ /**
243
+ * The resolved file URL.
244
+ *
245
+ * @const {URL} file
246
+ */
247
+ const file: URL = resolveModule('@/internal/fs', import.meta.url, { aliases })
248
+
249
+ console.dir(directory)
250
+ console.dir(file)
251
+ ```
252
+
218
253
  ### Rewrite an extension
219
254
 
220
255
  ```ts
@@ -987,7 +1022,7 @@ Resolve an aliased `specifier`.
987
1022
  - `specifier` (`string`)
988
1023
  — the specifier using an alias
989
1024
  - `options` ([`ResolveAliasOptions`](#resolvealiasoptions) | `null` | `undefined`)
990
- — alias resolution options
1025
+ options for alias resolution
991
1026
 
992
1027
  #### Returns
993
1028
 
@@ -1021,7 +1056,7 @@ Adds support for:
1021
1056
  - `parent` ([`ModuleId`](#moduleid))
1022
1057
  — the url of the parent module
1023
1058
  - `options` ([`ResolveModuleOptions`](#resolvemoduleoptions))
1024
- — module resolution options
1059
+ options for module resolution
1025
1060
 
1026
1061
  #### Returns
1027
1062
 
@@ -1144,34 +1179,6 @@ They will be added to this union automatically.
1144
1179
  type BufferEncoding = BufferEncodingMap[keyof BufferEncodingMap]
1145
1180
  ```
1146
1181
 
1147
- ### `ChangeExtFn<[Ext]>`
1148
-
1149
- Get a new file extension for `url` (`type`).
1150
-
1151
- Returning an empty string (`''`), `null`, or `undefined` will remove the current file extension.
1152
-
1153
- ```ts
1154
- type ChangeExtFn<
1155
- Ext extends string | null | undefined = string | null | undefined
1156
- > = (this: void, url: URL, specifier: string) => Ext
1157
- ```
1158
-
1159
- #### Type Parameters
1160
-
1161
- - `Ext` (`string` | `null` | `undefined`, optional)
1162
- — the new file extension
1163
-
1164
- #### Parameters
1165
-
1166
- - `url` (`URL`)
1167
- — the resolved module URL
1168
- - `specifier` (`string`)
1169
- — the module specifier being resolved
1170
-
1171
- #### Returns
1172
-
1173
- (`Ext`) The new file extension
1174
-
1175
1182
  ### `ConditionMap`
1176
1183
 
1177
1184
  Registry of export/import conditions (`interface`).
@@ -1237,6 +1244,20 @@ A file extension (`type`).
1237
1244
  type Ext = `${Dot}${string}`
1238
1245
  ```
1239
1246
 
1247
+ ### `ExtensionRewrites`
1248
+
1249
+ Record, where each key is the file extension of a module specifier
1250
+ and each value is a replacement file extension (`type`).
1251
+
1252
+ > 👉 **Note**: Replacement file extensions are normalized and do not need to begin with a dot character (`'.'`);
1253
+ > falsy values will remove an extension.
1254
+
1255
+ ```ts
1256
+ type ExtensionRewrites = {
1257
+ [K in EmptyString | Ext]?: string | false | null | undefined
1258
+ }
1259
+ ```
1260
+
1240
1261
  ### `FileContent`
1241
1262
 
1242
1263
  Union of values that can occur where file content is expected (`type`).
@@ -1258,6 +1279,38 @@ The file system API (`interface`).
1258
1279
  - `stat` ([`Stat`](#stat))
1259
1280
  — get information about a directory or file
1260
1281
 
1282
+ ### `GetNewExtension<[T]>`
1283
+
1284
+ Get a new file extension for a `url` (`type`).
1285
+
1286
+ Returning an empty string (`''`), `false`, `null`, or `undefined` will remove the current file extension.
1287
+
1288
+ ```ts
1289
+ type GetNewExtension<
1290
+ T extends string | false | null | undefined =
1291
+ | string
1292
+ | false
1293
+ | null
1294
+ | undefined
1295
+ > = (this: void, url: URL, specifier: string) => T
1296
+ ```
1297
+
1298
+ #### Type Parameters
1299
+
1300
+ - `T` (`string` | `false` | `null` | `undefined`, optional)
1301
+ — the new file extension
1302
+
1303
+ #### Parameters
1304
+
1305
+ - `url` (`URL`)
1306
+ — the resolved module URL
1307
+ - `specifier` (`string`)
1308
+ — the module specifier being resolved
1309
+
1310
+ #### Returns
1311
+
1312
+ (`T`) The new file extension
1313
+
1261
1314
  ### `GetSourceContext`
1262
1315
 
1263
1316
  Source code retrieval context (`interface`).
@@ -1557,7 +1610,7 @@ Options for path alias resolution (`interface`).
1557
1610
 
1558
1611
  ### `ResolveModuleOptions`
1559
1612
 
1560
- Options for path alias resolution (`interface`).
1613
+ Options for module resolution (`interface`).
1561
1614
 
1562
1615
  #### Properties
1563
1616
 
@@ -1571,9 +1624,12 @@ Options for path alias resolution (`interface`).
1571
1624
  - `cwd?` ([`ModuleId`](#moduleid) | `null` | `undefined`)
1572
1625
  — the url of the directory to resolve path `aliases` from
1573
1626
  - **default**: [`cwd()`](#cwd)
1574
- - `ext?` ([`ChangeExtFn`](#changeextfnext) | `string` | `null` | `undefined`)
1575
- a replacement file extension or a function that returns a file extension.
1576
- > \:point\_right: **note**: an empty string (`''`) or `null` will remove a file extension
1627
+ <!--lint disable-->
1628
+ - `ext?` ([`ExtensionRewrites`](#extensionrewrites) | [`GetNewExtension`](#getnewextensiont) | `false` | `string` | `null` | `undefined`)
1629
+ a replacement file extension, a record of replacement file extensions, or a function that returns a replacement file extension
1630
+ <!--lint enable-->
1631
+ > \:point\_right: **note**: replacement file extensions are normalized and do not need to begin
1632
+ > with a dot character (`'.'`); an empty string (`''`), `false`, or `null` will remove an extension
1577
1633
  - `extensions?` ([`List<string>`](#listt) | `null` | `undefined`)
1578
1634
  — the module extensions to probe for
1579
1635
  - **default**: [`defaultExtensions`](#defaultextensions)
package/dist/index.d.mts CHANGED
@@ -605,7 +605,7 @@ declare function readPackageJson<T extends Awaitable<PackageJson | null>>(this:
605
605
  * @param {string} specifier
606
606
  * The specifier using an alias
607
607
  * @param {ResolveAliasOptions | null | undefined} [options]
608
- * Alias resolution options
608
+ * Options for alias resolution
609
609
  * @return {string | null}
610
610
  * The specifier of the aliased module
611
611
  */
@@ -646,7 +646,7 @@ declare function resolveAlias(this: void, specifier: string, options?: ResolveAl
646
646
  * @param {ModuleId} parent
647
647
  * The URL of the parent module
648
648
  * @param {ResolveModuleOptions | null | undefined} [options]
649
- * Module resolution options
649
+ * Options for module resolution
650
650
  * @return {T}
651
651
  * The resolved URL
652
652
  * @throws {NodeError}
@@ -1109,35 +1109,6 @@ type Awaitable<T> = PromiseLike<T> | T;
1109
1109
  */
1110
1110
  type BufferEncoding = BufferEncodingMap[keyof BufferEncodingMap];
1111
1111
 
1112
- /**
1113
- * @file Type Aliases - ChangeExtFn
1114
- * @module mlly/types/ChangeExtFn
1115
- */
1116
- /**
1117
- * Get a new file extension for `url`.
1118
- *
1119
- * Returning an empty string (`''`), `null`, or `undefined` will remove the
1120
- * current file extension.
1121
- *
1122
- * ::: info
1123
- * The new file extension need not begin with a dot character (`'.'`).
1124
- * :::
1125
- *
1126
- * @see {@linkcode URL}
1127
- * @see https://github.com/flex-development/pathe/tree/1.0.3#changeextpath-string-ext-nullablestring-string
1128
- *
1129
- * @template {string | null | undefined} Ext
1130
- * The new file extension
1131
- *
1132
- * @param {URL} url
1133
- * The resolved module URL
1134
- * @param {string} specifier
1135
- * The module specifier being resolved
1136
- * @return {Ext}
1137
- * The new file extension
1138
- */
1139
- type ChangeExtFn<Ext extends string | null | undefined = string | null | undefined> = (this: void, url: URL, specifier: string) => Ext;
1140
-
1141
1112
  /**
1142
1113
  * @file Type Aliases - Condition
1143
1114
  * @module mlly/types/Condition
@@ -1209,6 +1180,25 @@ type EmptyString = '';
1209
1180
  */
1210
1181
  type Ext = `${Dot}${string}`;
1211
1182
 
1183
+ /**
1184
+ * @file Type Aliases - ExtensionRewrites
1185
+ * @module mlly/types/ExtensionRewrites
1186
+ */
1187
+
1188
+ /**
1189
+ * Record, where each key is the file extension of a module specifier and
1190
+ * each value is a replacement file extension.
1191
+ *
1192
+ * > 👉 **Note**: Replacement file extensions are normalized and do not need to
1193
+ * > begin with a dot character (`'.'`); falsy values will remove an extension.
1194
+ *
1195
+ * @see {@linkcode EmptyString}
1196
+ * @see {@linkcode Ext}
1197
+ */
1198
+ type ExtensionRewrites = {
1199
+ [K in EmptyString | Ext]?: string | false | null | undefined;
1200
+ };
1201
+
1212
1202
  /**
1213
1203
  * @file Type Aliases - FileContent
1214
1204
  * @module mlly/types/FileContent
@@ -1220,6 +1210,36 @@ type Ext = `${Dot}${string}`;
1220
1210
  */
1221
1211
  type FileContent = Uint8Array | string;
1222
1212
 
1213
+ /**
1214
+ * @file Type Aliases - GetNewExtension
1215
+ * @module mlly/types/GetNewExtension
1216
+ */
1217
+ /**
1218
+ * Get a new file extension for a `url`.
1219
+ *
1220
+ * Returning an empty string (`''`), `false`, `null`, or `undefined`
1221
+ * will remove the current file extension.
1222
+ *
1223
+ * ::: info
1224
+ * File extensions are normalized and
1225
+ * do not need to begin with a dot character (`'.'`).
1226
+ * :::
1227
+ *
1228
+ * @see {@linkcode URL}
1229
+ * @see https://github.com/flex-development/pathe/tree/1.0.3#changeextpath-string-ext-nullablestring-string
1230
+ *
1231
+ * @template {string | false | null | undefined} [T]
1232
+ * The new file extension
1233
+ *
1234
+ * @param {URL} url
1235
+ * The resolved module URL
1236
+ * @param {string} specifier
1237
+ * The module specifier being resolved
1238
+ * @return {T}
1239
+ * The new file extension
1240
+ */
1241
+ type GetNewExtension<T extends string | false | null | undefined = string | false | null | undefined> = (this: void, url: URL, specifier: string) => T;
1242
+
1223
1243
  /**
1224
1244
  * @file Type Aliases - GetSourceHandler
1225
1245
  * @module mlly/types/GetSourceHandler
@@ -1760,7 +1780,7 @@ interface ResolveAliasOptions {
1760
1780
  */
1761
1781
 
1762
1782
  /**
1763
- * Module resolution options.
1783
+ * Options for module resolution.
1764
1784
  */
1765
1785
  interface ResolveModuleOptions {
1766
1786
  /**
@@ -1792,14 +1812,17 @@ interface ResolveModuleOptions {
1792
1812
  */
1793
1813
  cwd?: ModuleId | null | undefined;
1794
1814
  /**
1795
- * A replacement file extension or a function that returns a file extension.
1815
+ * A replacement file extension, a record of replacement file extensions,
1816
+ * or a function that returns a replacement file extension.
1796
1817
  *
1797
- * > 👉 **Note**: An empty string (`''`) or `null` will
1798
- * > remove a file extension.
1818
+ * > 👉 **Note**: Replacement file extensions are normalized and do not
1819
+ * > need to begin with a dot character (`'.'`); an empty string (`''`),
1820
+ * > `false`, or `null` will remove an extension.
1799
1821
  *
1800
- * @see {@linkcode ChangeExtFn}
1822
+ * @see {@linkcode ExtensionRewrites}
1823
+ * @see {@linkcode GetNewExtension}
1801
1824
  */
1802
- ext?: ChangeExtFn | string | null | undefined;
1825
+ ext?: ExtensionRewrites | GetNewExtension | string | false | null | undefined;
1803
1826
  /**
1804
1827
  * The module extensions to probe for.
1805
1828
  *
@@ -1884,4 +1907,4 @@ interface Stats {
1884
1907
  }
1885
1908
 
1886
1909
  export { canParseUrl, cwd, defaultConditions, defaultExtensions, defaultMainFields, extensionFormatMap, formats, getSource, isAbsoluteSpecifier, isArrayIndex, isBareSpecifier, isDirectory, isFile, isImportsSubpath, isModuleId, isRelativeSpecifier, legacyMainResolve, lookupPackageScope, moduleResolve, packageExportsResolve, packageImportsExportsResolve, packageImportsResolve, packageResolve, packageSelfResolve, packageTargetResolve, patternKeyCompare, patternMatch, readPackageJson, resolveAlias, resolveModule, resolver_d as resolver, root, toRelativeSpecifier, toUrl };
1887
- export type { Aliases, Awaitable, BufferEncoding, BufferEncodingMap, ChangeExtFn, Condition, ConditionMap, Dot, EmptyArray, EmptyObject, EmptyString, Ext, FileContent, FileSystem, GetSourceContext, GetSourceHandler, GetSourceHandlers, GetSourceOptions, IsDirectory, IsFile, List, MainField, MainFieldMap, ModuleFormat, ModuleFormatMap, ModuleId, Numeric, PatternKeyComparison, PatternKeyComparisonMap, PatternMatch, Protocol, ProtocolMap, ReadFile, Realpath, ResolveAliasOptions, ResolveModuleOptions, Stat, Stats };
1910
+ export type { Aliases, Awaitable, BufferEncoding, BufferEncodingMap, Condition, ConditionMap, Dot, EmptyArray, EmptyObject, EmptyString, Ext, ExtensionRewrites, FileContent, FileSystem, GetNewExtension, GetSourceContext, GetSourceHandler, GetSourceHandlers, GetSourceOptions, IsDirectory, IsFile, List, MainField, MainFieldMap, ModuleFormat, ModuleFormatMap, ModuleId, Numeric, PatternKeyComparison, PatternKeyComparisonMap, PatternMatch, Protocol, ProtocolMap, ReadFile, Realpath, ResolveAliasOptions, ResolveModuleOptions, Stat, Stats };
@@ -1 +1 @@
1
- var i=Object.defineProperty;var a=(t,e)=>i(t,"name",{value:e,configurable:!0});import O from"#internal/constant";import U from"#internal/identity";import x from"#internal/is-promise";import D from"#lib/default-extensions";import y from"#lib/resolve-alias";import{moduleResolve as _}from"#lib/resolver";import{codes as f,isNodeError as N}from"@flex-development/errnode";import m from"@flex-development/pathe";var k=P;function P(t,e,r){let n;try{n=_(y(t,{...r,parent:e})??t,e,r?.conditions,r?.mainFields,r?.preserveSymlinks,r?.fs)}catch(d){return c(d,t,e,r)}return x(n)?n.then(d=>h(d,t,r?.ext),d=>c(d,t,e,r)):h(n,t,r?.ext)}a(P,"resolveModule");function h(t,e,r){return t.protocol==="file:"&&r!==void 0&&(t.href=typeof r=="function"?m.changeExt(t.href,r(t,e)):m.changeExt(t.href,r),t=new URL(m.toPosix(t.href).replace(/\/index$/,m.sep))),t}a(h,"changeExt");function c(t,e,r,n){const d=new Set([f.ERR_MODULE_NOT_FOUND,f.ERR_UNSUPPORTED_DIR_IMPORT]);if(N(t)&&d.has(t.code)){const E=[...n?.extensions??D],R=[];let s,l=[];t.code===f.ERR_MODULE_NOT_FOUND&&!t.url&&(l=[e.startsWith("@types/")?e:"@types/"+e].flatMap(o=>[o,o+m.sep+"index.d.ts",o+m.sep+"index.d.mts",o+m.sep+"index.d.cts"])),t.code===f.ERR_MODULE_NOT_FOUND&&t.url&&(l=E.map(o=>e+m.formatExt(o))),t.code===f.ERR_UNSUPPORTED_DIR_IMPORT&&(l=E.map(o=>e+m.sep+"index"+m.formatExt(o)));for(let o of l){try{if(s=_(o,r,n?.conditions,n?.mainFields,n?.preserveSymlinks,n?.fs),!x(s))return h(s,e,n?.ext)}catch{continue}R.push(s.then(U,O(void 0)))}if(R.length)return Promise.all(R).then(o=>{for(const u of o)if(u)return h(u,e,n?.ext);throw t})}throw t}a(c,"retry");export{k as default};
1
+ var O=Object.defineProperty;var a=(t,n)=>O(t,"name",{value:n,configurable:!0});import c from"#internal/constant";import U from"#internal/identity";import _ from"#internal/is-promise";import y from"#lib/default-extensions";import D from"#lib/resolve-alias";import{moduleResolve as i}from"#lib/resolver";import{codes as l,isNodeError as N}from"@flex-development/errnode";import m from"@flex-development/pathe";var k=P;function P(t,n,e){t=D(t,{...e,parent:n})??t;let r;try{r=i(t,n,e?.conditions,e?.mainFields,e?.preserveSymlinks,e?.fs)}catch(d){return x(d,t,n,e)}return _(r)?r.then(d=>u(d,t,e?.ext),d=>x(d,t,n,e)):u(r,t,e?.ext)}a(P,"resolveModule");function x(t,n,e,r){const d=new Set([l.ERR_MODULE_NOT_FOUND,l.ERR_UNSUPPORTED_DIR_IMPORT]);if(N(t)&&d.has(t.code)){const h=[...r?.extensions??y],R=[];let f,s=[];t.code===l.ERR_MODULE_NOT_FOUND&&!t.url&&(s=[n.startsWith("@types/")?n:"@types/"+n].flatMap(o=>[o,o+m.sep+"index.d.ts",o+m.sep+"index.d.mts",o+m.sep+"index.d.cts"])),t.code===l.ERR_MODULE_NOT_FOUND&&t.url&&(s=h.map(o=>n+m.formatExt(o))),t.code===l.ERR_UNSUPPORTED_DIR_IMPORT&&(s=h.map(o=>n+m.sep+"index"+m.formatExt(o)));for(let o of s){try{if(f=i(o,e,r?.conditions,r?.mainFields,r?.preserveSymlinks,r?.fs),!_(f))return u(f,n,r?.ext)}catch{continue}R.push(f.then(U,c(void 0)))}if(R.length)return Promise.all(R).then(o=>{for(const E of o)if(E)return u(E,n,r?.ext);throw t})}throw t}a(x,"retry");function u(t,n,e){if(t.protocol==="file:"&&e!==void 0){let r;typeof e=="function"?r=e(t,n):typeof e=="object"&&e?r=m.extToValue(t.href,e):r=e,t.href=m.changeExt(t.href,r||null),t=new URL(m.toPosix(t.href).replace(/\/index$/,m.sep))}return t}a(u,"rewriteExtension");export{k as default};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@flex-development/mlly",
3
3
  "description": "ESM utilities for modern tooling — spec-compliant, developer-friendly, and fully typed",
4
- "version": "1.0.0-beta.5",
4
+ "version": "1.0.0-beta.6",
5
5
  "keywords": [
6
6
  "bundle",
7
7
  "cli",
@@ -72,9 +72,7 @@
72
72
  "default": "./dist/interfaces/*.d.mts"
73
73
  },
74
74
  "#internal/fs": {
75
- "types": {
76
- "mlly": "./src/internal/fs.d.mts"
77
- },
75
+ "types": "./src/internal/fs.d.mts",
78
76
  "browser": {
79
77
  "mlly": "./src/internal/fs.browser.mts",
80
78
  "default": "./dist/internal/fs.browser.mjs"
@@ -216,7 +214,7 @@
216
214
  "typescript": "5.9.3",
217
215
  "unified": "11.0.5",
218
216
  "vfile": "6.0.3",
219
- "vite-tsconfig-paths": "6.1.0",
217
+ "vite-tsconfig-paths": "6.1.1",
220
218
  "vitest": "4.0.18"
221
219
  },
222
220
  "resolutions": {