@flex-development/mlly 1.0.0-alpha.1

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/LICENSE.md +28 -0
  3. package/README.md +17 -0
  4. package/changelog.config.cts +204 -0
  5. package/dist/constants.d.mts +19 -0
  6. package/dist/constants.mjs +24 -0
  7. package/dist/index.d.mts +8 -0
  8. package/dist/index.mjs +4 -0
  9. package/dist/interfaces/import-dynamic.d.mts +23 -0
  10. package/dist/interfaces/import-dynamic.mjs +0 -0
  11. package/dist/interfaces/import-static.d.mts +19 -0
  12. package/dist/interfaces/import-static.mjs +0 -0
  13. package/dist/interfaces/index.d.mts +12 -0
  14. package/dist/interfaces/index.mjs +0 -0
  15. package/dist/interfaces/options-resolve-alias.d.mts +69 -0
  16. package/dist/interfaces/options-resolve-alias.mjs +0 -0
  17. package/dist/interfaces/options-resolve.d.mts +60 -0
  18. package/dist/interfaces/options-resolve.mjs +0 -0
  19. package/dist/interfaces/statement-export.d.mts +31 -0
  20. package/dist/interfaces/statement-export.mjs +0 -0
  21. package/dist/interfaces/statement-import.d.mts +27 -0
  22. package/dist/interfaces/statement-import.mjs +0 -0
  23. package/dist/interfaces/statement-require.d.mts +27 -0
  24. package/dist/interfaces/statement-require.mjs +0 -0
  25. package/dist/interfaces/statement.d.mts +33 -0
  26. package/dist/interfaces/statement.mjs +0 -0
  27. package/dist/internal/compiler-options-json.d.mts +111 -0
  28. package/dist/internal/compiler-options-json.mjs +0 -0
  29. package/dist/internal/constants.d.mts +70 -0
  30. package/dist/internal/constants.mjs +18 -0
  31. package/dist/internal/get-compiler-options.d.mts +21 -0
  32. package/dist/internal/get-compiler-options.mjs +14 -0
  33. package/dist/internal/index.d.mts +7 -0
  34. package/dist/internal/index.mjs +5 -0
  35. package/dist/lib/detect-syntax.d.mts +21 -0
  36. package/dist/lib/detect-syntax.mjs +11 -0
  37. package/dist/lib/extract-statements.d.mts +21 -0
  38. package/dist/lib/extract-statements.mjs +18 -0
  39. package/dist/lib/find-dynamic-imports.d.mts +15 -0
  40. package/dist/lib/find-dynamic-imports.mjs +20 -0
  41. package/dist/lib/find-exports.d.mts +15 -0
  42. package/dist/lib/find-exports.mjs +53 -0
  43. package/dist/lib/find-requires.d.mts +17 -0
  44. package/dist/lib/find-requires.mjs +19 -0
  45. package/dist/lib/find-static-imports.d.mts +15 -0
  46. package/dist/lib/find-static-imports.mjs +20 -0
  47. package/dist/lib/has-cjs-syntax.d.mts +22 -0
  48. package/dist/lib/has-cjs-syntax.mjs +6 -0
  49. package/dist/lib/has-esm-syntax.d.mts +18 -0
  50. package/dist/lib/has-esm-syntax.mjs +6 -0
  51. package/dist/lib/index.d.mts +20 -0
  52. package/dist/lib/index.mjs +34 -0
  53. package/dist/lib/resolve-alias.d.mts +20 -0
  54. package/dist/lib/resolve-alias.mjs +41 -0
  55. package/dist/lib/resolve-aliases.d.mts +17 -0
  56. package/dist/lib/resolve-aliases.mjs +34 -0
  57. package/dist/lib/resolve-module.d.mts +31 -0
  58. package/dist/lib/resolve-module.mjs +74 -0
  59. package/dist/lib/resolve-modules.d.mts +19 -0
  60. package/dist/lib/resolve-modules.mjs +29 -0
  61. package/dist/lib/to-absolute-specifier.d.mts +22 -0
  62. package/dist/lib/to-absolute-specifier.mjs +20 -0
  63. package/dist/lib/to-bare-specifier.d.mts +28 -0
  64. package/dist/lib/to-bare-specifier.mjs +78 -0
  65. package/dist/lib/to-data-url.d.mts +29 -0
  66. package/dist/lib/to-data-url.mjs +7 -0
  67. package/dist/lib/to-relative-specifier.d.mts +22 -0
  68. package/dist/lib/to-relative-specifier.mjs +17 -0
  69. package/dist/types/declaration.d.mts +9 -0
  70. package/dist/types/declaration.mjs +0 -0
  71. package/dist/types/ext.d.mts +9 -0
  72. package/dist/types/ext.mjs +0 -0
  73. package/dist/types/index.d.mts +9 -0
  74. package/dist/types/index.mjs +0 -0
  75. package/dist/types/mime-type.d.mts +11 -0
  76. package/dist/types/mime-type.mjs +0 -0
  77. package/dist/types/specifier-type.d.mts +11 -0
  78. package/dist/types/specifier-type.mjs +0 -0
  79. package/dist/types/statement-type.d.mts +9 -0
  80. package/dist/types/statement-type.mjs +0 -0
  81. package/package.json +197 -0
@@ -0,0 +1,19 @@
1
+ import { REQUIRE_STATEMENT_REGEX } from "../internal/index.mjs";
2
+ const findRequires = (code) => {
3
+ return [...code.matchAll(REQUIRE_STATEMENT_REGEX)].map((match) => {
4
+ const { 0: statement = "", index: start = 0, groups = {} } = match;
5
+ const { imports = "", specifier = "", type = "" } = groups;
6
+ return {
7
+ code: statement,
8
+ end: start + statement.length,
9
+ imports: imports === "" || type === "require.resolve" ? [] : /const *\w/.test(statement) ? ["default"] : imports.split(",").map((name) => name.trim()),
10
+ specifier,
11
+ start,
12
+ type
13
+ };
14
+ });
15
+ };
16
+ var find_requires_default = findRequires;
17
+ export {
18
+ find_requires_default as default
19
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @file findStaticImports
3
+ * @module mlly/lib/findStaticImports
4
+ */
5
+ import type { StaticImport } from '../interfaces/index.mjs';
6
+ /**
7
+ * Finds all static import statements in `code`. Ignores matches in comments.
8
+ *
9
+ * @see {@link StaticImport}
10
+ *
11
+ * @param {string} code - Code to check
12
+ * @return {StaticImport[]} Static import statement objects
13
+ */
14
+ declare const findStaticImports: (code: string) => StaticImport[];
15
+ export default findStaticImports;
@@ -0,0 +1,20 @@
1
+ import { STATIC_IMPORT_REGEX } from "../internal/index.mjs";
2
+ const findStaticImports = (code) => {
3
+ return [...code.matchAll(STATIC_IMPORT_REGEX)].map((match) => {
4
+ const { 0: statement = "", index: start = 0, groups = {} } = match;
5
+ const { imports = "", specifier = "" } = groups;
6
+ const star = imports.startsWith("* as");
7
+ return {
8
+ code: statement,
9
+ end: start + statement.length,
10
+ imports: star ? [imports.trim()] : imports.replace(/^type\s*|[{}]/gm, "").split(/,\n?/).map((name) => name.trim()),
11
+ specifier,
12
+ start,
13
+ type: star ? "star" : /{(?<imports>[\w\t\n\r ,]+)}/gm.test(statement) ? "named" : "default"
14
+ };
15
+ });
16
+ };
17
+ var find_static_imports_default = findStaticImports;
18
+ export {
19
+ find_static_imports_default as default
20
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @file hasCJSSyntax
3
+ * @module mlly/lib/hasCJSSyntax
4
+ */
5
+ /**
6
+ * Detects if `code` contains CommonJS syntax. Ignores matches in comments.
7
+ *
8
+ * Syntax patterns:
9
+ *
10
+ * - `__dirname`
11
+ * - `__filename`
12
+ * - `await import`
13
+ * - `exports`
14
+ * - `module.exports`
15
+ * - `require`
16
+ * - `require.*`
17
+ *
18
+ * @param {string} code - Code to check
19
+ * @return {boolean} `true` if `code` contains cjs syntax, `false` otherwise
20
+ */
21
+ declare const hasCJSSyntax: (code: string) => boolean;
22
+ export default hasCJSSyntax;
@@ -0,0 +1,6 @@
1
+ import { CJS_SYNTAX_REGEX } from "../internal/index.mjs";
2
+ const hasCJSSyntax = (code) => !!code.match(CJS_SYNTAX_REGEX);
3
+ var has_cjs_syntax_default = hasCJSSyntax;
4
+ export {
5
+ has_cjs_syntax_default as default
6
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @file hasESMSyntax
3
+ * @module mlly/lib/hasESMSyntax
4
+ */
5
+ /**
6
+ * Detects if `code` contains ESM syntax. Ignores matches in comments.
7
+ *
8
+ * Syntax patterns:
9
+ *
10
+ * - `export` (declaration, default, named, star)
11
+ * - `import` (default, dynamic, named, star)
12
+ * - `import.meta.(env|resolve|url)`
13
+ *
14
+ * @param {string} code - Code to check
15
+ * @return {boolean} `true` if `code` contains esm syntax, `false` otherwise
16
+ */
17
+ declare const hasESMSyntax: (code: string) => boolean;
18
+ export default hasESMSyntax;
@@ -0,0 +1,6 @@
1
+ import { ESM_SYNTAX_REGEX } from "../internal/index.mjs";
2
+ const hasESMSyntax = (code) => !!code.match(ESM_SYNTAX_REGEX);
3
+ var has_esm_syntax_default = hasESMSyntax;
4
+ export {
5
+ has_esm_syntax_default as default
6
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @file Library
3
+ * @module mlly/lib
4
+ */
5
+ export { default as detectSyntax } from './detect-syntax.mjs';
6
+ export { default as extractStatements } from './extract-statements.mjs';
7
+ export { default as findDynamicImports } from './find-dynamic-imports.mjs';
8
+ export { default as findExports } from './find-exports.mjs';
9
+ export { default as findRequires } from './find-requires.mjs';
10
+ export { default as findStaticImports } from './find-static-imports.mjs';
11
+ export { default as hasCJSSyntax } from './has-cjs-syntax.mjs';
12
+ export { default as hasESMSyntax } from './has-esm-syntax.mjs';
13
+ export { default as resolveAlias } from './resolve-alias.mjs';
14
+ export { default as resolveAliases } from './resolve-aliases.mjs';
15
+ export { default as resolveModule } from './resolve-module.mjs';
16
+ export { default as resolveModules } from './resolve-modules.mjs';
17
+ export { default as toAbsoluteSpecifier } from './to-absolute-specifier.mjs';
18
+ export { default as toBareSpecifier } from './to-bare-specifier.mjs';
19
+ export { default as toDataURL } from './to-data-url.mjs';
20
+ export { default as toRelativeSpecifier } from './to-relative-specifier.mjs';
@@ -0,0 +1,34 @@
1
+ import { default as default2 } from "./detect-syntax.mjs";
2
+ import { default as default3 } from "./extract-statements.mjs";
3
+ import { default as default4 } from "./find-dynamic-imports.mjs";
4
+ import { default as default5 } from "./find-exports.mjs";
5
+ import { default as default6 } from "./find-requires.mjs";
6
+ import { default as default7 } from "./find-static-imports.mjs";
7
+ import { default as default8 } from "./has-cjs-syntax.mjs";
8
+ import { default as default9 } from "./has-esm-syntax.mjs";
9
+ import { default as default10 } from "./resolve-alias.mjs";
10
+ import { default as default11 } from "./resolve-aliases.mjs";
11
+ import { default as default12 } from "./resolve-module.mjs";
12
+ import { default as default13 } from "./resolve-modules.mjs";
13
+ import { default as default14 } from "./to-absolute-specifier.mjs";
14
+ import { default as default15 } from "./to-bare-specifier.mjs";
15
+ import { default as default16 } from "./to-data-url.mjs";
16
+ import { default as default17 } from "./to-relative-specifier.mjs";
17
+ export {
18
+ default2 as detectSyntax,
19
+ default3 as extractStatements,
20
+ default4 as findDynamicImports,
21
+ default5 as findExports,
22
+ default6 as findRequires,
23
+ default7 as findStaticImports,
24
+ default8 as hasCJSSyntax,
25
+ default9 as hasESMSyntax,
26
+ default10 as resolveAlias,
27
+ default11 as resolveAliases,
28
+ default12 as resolveModule,
29
+ default13 as resolveModules,
30
+ default14 as toAbsoluteSpecifier,
31
+ default15 as toBareSpecifier,
32
+ default16 as toDataURL,
33
+ default17 as toRelativeSpecifier
34
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @file resolveAlias
3
+ * @module mlly/lib/resolveAlias
4
+ */
5
+ import type { ResolveAliasOptions } from '../interfaces/index.mjs';
6
+ /**
7
+ * Resolves a path alias in `specifier`; does nothing if a path match isn't
8
+ * found.
9
+ *
10
+ * If `options.tsconfig` is found, `options.baseUrl` and `options.paths` will
11
+ * be overridden with values from the config file.
12
+ *
13
+ * @see {@link ResolveAliasOptions}
14
+ *
15
+ * @param {string} specifier - Module specifier
16
+ * @param {ResolveAliasOptions} [options={}] - Resolve alias options
17
+ * @return {string} `specifier` unmodified or with path alias resolved
18
+ */
19
+ declare const resolveAlias: (specifier: string, options?: ResolveAliasOptions) => string;
20
+ export default resolveAlias;
@@ -0,0 +1,41 @@
1
+ import { RESOLVE_EXTENSIONS } from "../constants.mjs";
2
+ import { getCompilerOptions } from "../internal/index.mjs";
3
+ import { createMatchPath } from "tsconfig-paths";
4
+ import upath from "upath";
5
+ import toRelativeSpecifier from "./to-relative-specifier.mjs";
6
+ const resolveAlias = (specifier, options = {}) => {
7
+ const {
8
+ extensions = RESOLVE_EXTENSIONS,
9
+ fileExists,
10
+ mainFields = ["main", "module"],
11
+ parent,
12
+ readFile,
13
+ tsconfig
14
+ } = options;
15
+ let { baseUrl = process.cwd(), paths = {} } = options;
16
+ if (tsconfig) {
17
+ const { baseUrl: b = ".", paths: p = paths } = getCompilerOptions(tsconfig);
18
+ baseUrl = upath.resolve(upath.dirname(tsconfig), b);
19
+ paths = p;
20
+ }
21
+ const matcher = createMatchPath(
22
+ baseUrl,
23
+ paths,
24
+ mainFields,
25
+ baseUrl.length > 0
26
+ );
27
+ let match = matcher(
28
+ specifier,
29
+ readFile,
30
+ fileExists,
31
+ extensions
32
+ );
33
+ if (!match)
34
+ return specifier;
35
+ match = /\/node_modules\//.test(match) ? match.replace(/.+\/node_modules\//, "") : parent ? toRelativeSpecifier(match, parent) : match;
36
+ return match;
37
+ };
38
+ var resolve_alias_default = resolveAlias;
39
+ export {
40
+ resolve_alias_default as default
41
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @file resolveAliases
3
+ * @module mlly/lib/resolveAliases
4
+ */
5
+ import type { ResolveAliasOptions } from '../interfaces/index.mjs';
6
+ /**
7
+ * Resolves path aliases in `code`.
8
+ *
9
+ * @see {@link ResolveAliasOptions}
10
+ * @see {@link resolveAlias}
11
+ *
12
+ * @param {string} code - Code containing path aliases
13
+ * @param {ResolveAliasOptions} [options={}] - Resolve alias options
14
+ * @return {string} `code` unmodified or with path aliases resolved
15
+ */
16
+ declare const resolveAliases: (code: string, options?: ResolveAliasOptions) => string;
17
+ export default resolveAliases;
@@ -0,0 +1,34 @@
1
+ import { getCompilerOptions } from "../internal/index.mjs";
2
+ import upath from "upath";
3
+ import extractStatements from "./extract-statements.mjs";
4
+ import resolveAlias from "./resolve-alias.mjs";
5
+ const resolveAliases = (code, options = {}) => {
6
+ const { tsconfig } = options;
7
+ let { baseUrl = process.cwd(), paths = {} } = options;
8
+ if (tsconfig) {
9
+ const { baseUrl: b = ".", paths: p = paths } = getCompilerOptions(tsconfig);
10
+ baseUrl = upath.resolve(upath.dirname(tsconfig), b);
11
+ paths = p;
12
+ }
13
+ for (const statement of extractStatements(code)) {
14
+ if (!statement.specifier)
15
+ continue;
16
+ const specifier = resolveAlias(statement.specifier, {
17
+ ...options,
18
+ baseUrl,
19
+ paths,
20
+ tsconfig: void 0
21
+ });
22
+ if (specifier === statement.specifier)
23
+ continue;
24
+ code = code.replace(
25
+ statement.code,
26
+ statement.code.replace(statement.specifier, specifier)
27
+ );
28
+ }
29
+ return code;
30
+ };
31
+ var resolve_aliases_default = resolveAliases;
32
+ export {
33
+ resolve_aliases_default as default
34
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @file resolveModule
3
+ * @module mlly/lib/resolveModule
4
+ */
5
+ import type { ResolveOptions } from '../interfaces/index.mjs';
6
+ /**
7
+ * Resolves `specifier` according to the [ESM Resolver algorithm][1], mostly 😉.
8
+ *
9
+ * Adds support for:
10
+ *
11
+ * - Resolving without file extensions and explicit `/index` usage
12
+ * - Resolving `@types/*` with **and** without explicit `@types/*` usage
13
+ * - Converting resolved modules into [bare][2] and [relative][3] specifiers
14
+ * - Removing and replacing file extensions
15
+ *
16
+ * [1]: https://nodejs.org/api/esm.html#esm_resolver_algorithm
17
+ * [2]: {@link toBareSpecifier}
18
+ * [3]: {@link toRelativeSpecifier}
19
+ *
20
+ * @see {@link ResolveOptions}
21
+ * @see {@link ErrnoException}
22
+ *
23
+ * @async
24
+ *
25
+ * @param {string} specifier - Module specifier to resolve
26
+ * @param {ResolveOptions} [options={}] - Resolve options
27
+ * @return {Promise<string>} Resolved module
28
+ * @throws {ErrnoException}
29
+ */
30
+ declare const resolveModule: (specifier: string, options?: ResolveOptions) => Promise<string>;
31
+ export default resolveModule;
@@ -0,0 +1,74 @@
1
+ import { CONDITIONS, RESOLVE_EXTENSIONS } from "../constants.mjs";
2
+ import isBuiltin from "@flex-development/is-builtin";
3
+ import { moduleResolve } from "import-meta-resolve";
4
+ import { pathToFileURL, URL } from "node:url";
5
+ import upath from "upath";
6
+ import toBareSpecifier from "./to-bare-specifier.mjs";
7
+ import toRelativeSpecifier from "./to-relative-specifier.mjs";
8
+ const resolveModule = async (specifier, options = {}) => {
9
+ const {
10
+ conditions = CONDITIONS,
11
+ ext,
12
+ extensions = RESOLVE_EXTENSIONS,
13
+ parent = import.meta.url,
14
+ preserveSymlinks = false,
15
+ ...opts
16
+ } = options;
17
+ const base = typeof parent === "string" ? parent.startsWith("file:") ? new URL(parent) : pathToFileURL(parent) : parent;
18
+ const tries = isBuiltin(specifier) || /^(?:data|https?):/.test(specifier) ? [] : extensions.flatMap((ext2) => {
19
+ return [specifier + ext2, specifier + "/index" + ext2].flatMap(($try) => {
20
+ return [$try, "@types/" + $try];
21
+ });
22
+ });
23
+ tries.unshift(specifier);
24
+ const ignore = /* @__PURE__ */ new Set([
25
+ "ERR_MODULE_NOT_FOUND",
26
+ "ERR_PACKAGE_PATH_NOT_EXPORTED",
27
+ "ERR_UNSUPPORTED_DIR_IMPORT"
28
+ ]);
29
+ let error;
30
+ let resolved;
31
+ for (const id of tries) {
32
+ try {
33
+ resolved = moduleResolve(
34
+ id,
35
+ base,
36
+ new Set(conditions),
37
+ preserveSymlinks
38
+ ).href;
39
+ } catch (e) {
40
+ if (id === specifier)
41
+ error = e;
42
+ if (ignore.has(e.code))
43
+ continue;
44
+ throw e;
45
+ }
46
+ if (resolved)
47
+ break;
48
+ }
49
+ if (!resolved)
50
+ throw error;
51
+ if (isBuiltin(resolved) || /^(?:data|https?):/.test(resolved))
52
+ return resolved;
53
+ const type = typeof opts.type === "function" ? await opts.type(resolved) : opts.type ?? "absolute";
54
+ if (type === "bare")
55
+ resolved = await toBareSpecifier(resolved, conditions);
56
+ if (type === "relative")
57
+ resolved = toRelativeSpecifier(resolved, parent);
58
+ if (ext !== void 0) {
59
+ if (ext === false) {
60
+ resolved = upath.removeExt(resolved, upath.extname(resolved));
61
+ } else if (type === "relative") {
62
+ resolved = upath.changeExt(
63
+ resolved,
64
+ typeof ext === "function" ? await ext(specifier, resolved) : ext
65
+ );
66
+ }
67
+ resolved = resolved.replace(/\/index$/, "");
68
+ }
69
+ return resolved;
70
+ };
71
+ var resolve_module_default = resolveModule;
72
+ export {
73
+ resolve_module_default as default
74
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @file resolveModules
3
+ * @module mlly/lib/resolveModules
4
+ */
5
+ import type { ResolveOptions } from '../interfaces/index.mjs';
6
+ /**
7
+ * Resolves all modules in `code`.
8
+ *
9
+ * @see {@link ResolveOptions}
10
+ * @see {@link resolveModule}
11
+ *
12
+ * @async
13
+ *
14
+ * @param {string} code - Code containing module specifiers
15
+ * @param {ResolveOptions} [options={}] - Resolve options
16
+ * @return {Promise<string>} `code` with modules resolved
17
+ */
18
+ declare const resolveModules: (code: string, options?: ResolveOptions) => Promise<string>;
19
+ export default resolveModules;
@@ -0,0 +1,29 @@
1
+ import upath from "upath";
2
+ import extractStatements from "./extract-statements.mjs";
3
+ import resolveModule from "./resolve-module.mjs";
4
+ const resolveModules = async (code, options = {}) => {
5
+ for (const statement of extractStatements(code)) {
6
+ if (!statement.specifier)
7
+ continue;
8
+ if (statement.specifier_type === "dynamic")
9
+ continue;
10
+ const type = (resolved) => {
11
+ return upath.isAbsolute(statement.specifier) || statement.specifier.startsWith("file:") ? "absolute" : /\/node_modules\//.test(resolved) ? "bare" : "relative";
12
+ };
13
+ code = code.replace(
14
+ statement.code,
15
+ statement.code.replace(
16
+ statement.specifier,
17
+ await resolveModule(statement.specifier, {
18
+ ...options,
19
+ type: options.type ?? type
20
+ })
21
+ )
22
+ );
23
+ }
24
+ return code;
25
+ };
26
+ var resolve_modules_default = resolveModules;
27
+ export {
28
+ resolve_modules_default as default
29
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @file toAbsoluteSpecifier
3
+ * @module mlly/lib/toAbsoluteSpecifier
4
+ */
5
+ import { URL } from 'node:url';
6
+ /**
7
+ * Converts `specifier` into an absolute specifier.
8
+ *
9
+ * ::: info
10
+ * The absolute specifier will only include a file extension if `specifier`
11
+ * includes a file extension.
12
+ * :::
13
+ *
14
+ * @see {@link URL}
15
+ * @see https://nodejs.org/api/esm.html#terminology
16
+ *
17
+ * @param {URL | string} specifier - Module specifier to convert
18
+ * @param {URL | string} [cwd=process.cwd()] - Current working directory
19
+ * @return {string} `specifier` as absolute specifier (file url)
20
+ */
21
+ declare const toAbsoluteSpecifier: (specifier: URL | string, cwd?: URL | string) => string;
22
+ export default toAbsoluteSpecifier;
@@ -0,0 +1,20 @@
1
+ import { fileURLToPath, pathToFileURL, URL } from "node:url";
2
+ import upath from "upath";
3
+ const toAbsoluteSpecifier = (specifier, cwd = process.cwd()) => {
4
+ if (cwd instanceof URL)
5
+ cwd = cwd.href;
6
+ if (specifier instanceof URL)
7
+ specifier = specifier.href;
8
+ if (cwd.startsWith("file:"))
9
+ cwd = fileURLToPath(cwd);
10
+ if (specifier.startsWith("file:"))
11
+ specifier = fileURLToPath(specifier);
12
+ if (!upath.isAbsolute(specifier))
13
+ specifier = upath.resolve(cwd, specifier);
14
+ cwd = pathToFileURL(cwd).href.replace(/\/$/, "") + "/";
15
+ return new URL(specifier, cwd).href;
16
+ };
17
+ var to_absolute_specifier_default = toAbsoluteSpecifier;
18
+ export {
19
+ to_absolute_specifier_default as default
20
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @file toBareSpecifier
3
+ * @module mlly/lib/toBareSpecifier
4
+ */
5
+ import type { ResolveOptions } from '../interfaces/index.mjs';
6
+ import { URL } from 'node:url';
7
+ /**
8
+ * Converts `specifier` into a bare specifier.
9
+ *
10
+ * ::: info
11
+ * The bare specifier will only include a file extension if `specifier` includes
12
+ * a file extension.
13
+ * :::
14
+ *
15
+ * @see {@link CONDITIONS}
16
+ * @see {@link URL}
17
+ * @see {@link ErrnoException}
18
+ * @see https://nodejs.org/api/esm.html#terminology
19
+ *
20
+ * @async
21
+ *
22
+ * @param {URL | string} specifier - File url or path to convert
23
+ * @param {ResolveOptions['conditions']} [conditions=CONDITIONS] - Conditions
24
+ * @return {string} `specifier` as bare specifier
25
+ * @throws {ErrnoException}
26
+ */
27
+ declare const toBareSpecifier: (specifier: URL | string, conditions?: ResolveOptions['conditions']) => Promise<string>;
28
+ export default toBareSpecifier;
@@ -0,0 +1,78 @@
1
+ import { CONDITIONS } from "../constants.mjs";
2
+ import isBuiltin from "@flex-development/is-builtin";
3
+ import { isNIL } from "@flex-development/tutils";
4
+ import { codes as errors } from "import-meta-resolve/lib/errors.js";
5
+ import {
6
+ findEntryInExports,
7
+ findPathInExports,
8
+ parseModuleId
9
+ } from "node-package-exports";
10
+ import { fileURLToPath, URL } from "node:url";
11
+ import { readPackageUp } from "read-pkg-up";
12
+ import upath from "upath";
13
+ const toBareSpecifier = async (specifier, conditions = CONDITIONS) => {
14
+ if (specifier instanceof URL)
15
+ specifier = specifier.href;
16
+ if (specifier.startsWith("file:"))
17
+ specifier = fileURLToPath(specifier);
18
+ if (isBuiltin(specifier))
19
+ return specifier;
20
+ const pkg = await readPackageUp({
21
+ cwd: specifier,
22
+ normalize: false
23
+ });
24
+ if (!pkg) {
25
+ const pkgerror = "- package.json not found";
26
+ throw new errors.ERR_INVALID_PACKAGE_CONFIG(pkgerror, `'${specifier}'`, "");
27
+ }
28
+ const normalize = (p) => {
29
+ return upath.format({
30
+ base: "",
31
+ dir: upath.dirname(p),
32
+ ext: "",
33
+ name: upath.basename(p, upath.extname(p)),
34
+ root: ""
35
+ }).replace(/^(\w)/, "./$1");
36
+ };
37
+ const {
38
+ name,
39
+ path,
40
+ raw: bare
41
+ } = parseModuleId(specifier.replace(/.*node_modules\//, ""));
42
+ if (name.startsWith("@types"))
43
+ return name.replace(/^@types\/(\w+)$/g, "$1");
44
+ const { exports } = pkg.packageJson;
45
+ if (isNIL(exports)) {
46
+ const { main = "", types = "" } = pkg.packageJson;
47
+ if (bare === name || path === main || path === types)
48
+ return name;
49
+ if ([normalize(main), normalize(types)].includes(normalize(path))) {
50
+ return name;
51
+ }
52
+ return bare;
53
+ }
54
+ if (path === findEntryInExports(exports, [...conditions]))
55
+ return name;
56
+ const { dir } = upath.parse(path.replace(/^\.\//, ""));
57
+ const tries = new Set(
58
+ [
59
+ path || ".",
60
+ ...dir.split("/").map((seg) => "./" + (path.split(seg + "/")[1] ?? ""))
61
+ ].map((trypath) => /^\.\/index(?:\..*)?$/.test(trypath) ? "." : trypath).filter((trypath) => trypath === "." || trypath.length > 2)
62
+ );
63
+ for (const trypath of tries) {
64
+ const exportpath = findPathInExports(trypath, exports, [
65
+ ...conditions
66
+ ]);
67
+ if (exportpath)
68
+ return upath.join(name, trypath);
69
+ }
70
+ throw new errors.ERR_PACKAGE_PATH_NOT_EXPORTED(
71
+ upath.dirname(pkg.path) + "/",
72
+ [...tries][0]
73
+ );
74
+ };
75
+ var to_bare_specifier_default = toBareSpecifier;
76
+ export {
77
+ to_bare_specifier_default as default
78
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @file toDataURL
3
+ * @module mlly/lib/toDataURL
4
+ */
5
+ import type { MIMEType } from '../types/index.mjs';
6
+ /**
7
+ * Converts `code` into a [`data:` URL][1] using `base64` encoding.
8
+ *
9
+ * ::: tip
10
+ * `data:` URLs only resolve [bare specifiers][2] for builtin modules and
11
+ * [absolute specifiers][2].
12
+ *
13
+ * Call [`await resolveModules(code)`][3] to ensure all specifiers are absolute
14
+ * or bare.
15
+ * :::
16
+ *
17
+ * [1]: https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
18
+ * [2]: https://nodejs.org/api/esm.html#terminology
19
+ * [3]: {@link ./resolve-modules.ts}
20
+ *
21
+ * @see {@link MIMEType}
22
+ * @see https://nodejs.org/api/esm.html#esm_data_imports
23
+ *
24
+ * @param {string} code - Code to convert
25
+ * @param {MIMEType} [mime='text/javascript'] - MIME type
26
+ * @return {string} `code` as `data:` URL
27
+ */
28
+ declare const toDataURL: (code: string, mime?: MIMEType) => string;
29
+ export default toDataURL;
@@ -0,0 +1,7 @@
1
+ const toDataURL = (code, mime = "text/javascript") => {
2
+ return `data:${mime};base64,${Buffer.from(code).toString("base64")}`;
3
+ };
4
+ var to_data_url_default = toDataURL;
5
+ export {
6
+ to_data_url_default as default
7
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @file toRelativeSpecifier
3
+ * @module mlly/lib/toRelativeSpecifier
4
+ */
5
+ import { URL } from 'node:url';
6
+ /**
7
+ * Converts `specifier` into a relative specifier.
8
+ *
9
+ * ::: info
10
+ * The relative specifier will only include a file extension if `specifier`
11
+ * includes a file extension.
12
+ * :::
13
+ *
14
+ * @see {@link URL}
15
+ * @see https://nodejs.org/api/esm.html#terminology
16
+ *
17
+ * @param {URL | string} specifier - Module specifier to convert
18
+ * @param {URL | string} parent - Parent module URL or path to resolve from
19
+ * @return {string} `specifier` as relative specifier
20
+ */
21
+ declare const toRelativeSpecifier: (specifier: URL | string, parent: URL | string) => string;
22
+ export default toRelativeSpecifier;