diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..eb5a316c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/napi/Cargo.lock b/napi/Cargo.lock new file mode 100644 index 00000000..92a9d2ab --- /dev/null +++ b/napi/Cargo.lock @@ -0,0 +1,610 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "ctor" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" +dependencies = [ + "quote", + "syn 2.0.39", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "napi" +version = "2.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1133249c46e92da921bafc8aba4912bf84d6c475f7625183772ed2d0844dc3a7" +dependencies = [ + "bitflags 2.4.1", + "ctor", + "napi-derive", + "napi-sys", + "once_cell", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "napi-build" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" + +[[package]] +name = "napi-derive" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0cca5738c6e81eb5ffd2c8ff2b4f05ece9c4c60c7e2b36cec6524492cf7f330" +dependencies = [ + "cfg-if", + "convert_case", + "napi-derive-backend", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "napi-derive-backend" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35960e5f33228192a9b661447d0dfe8f5a3790ff5b4058c4d67680ded4f65b91" +dependencies = [ + "convert_case", + "once_cell", + "proc-macro2", + "quote", + "regex", + "semver", + "syn 1.0.109", +] + +[[package]] +name = "napi-sys" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2503fa6af34dc83fb74888df8b22afe933b58d37daf7d80424b1c60c68196b8b" +dependencies = [ + "libloading", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "oxc_napi_resolver" +version = "0.0.0" +dependencies = [ + "napi", + "napi-build", + "napi-derive", + "oxc_resolver", +] + +[[package]] +name = "oxc_resolver" +version = "0.6.1" +dependencies = [ + "dashmap", + "dunce", + "indexmap", + "once_cell", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "tokio" +version = "1.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/napi/Cargo.toml b/napi/Cargo.toml index 70e68a72..038d884e 100644 --- a/napi/Cargo.toml +++ b/napi/Cargo.toml @@ -1,10 +1,7 @@ [package] -name = "oxc_napi_resolver" -version = "0.0.0" -publish = false - -[lints] -workspace = true +name = "oxc_napi_resolver" +version = "0.0.0" +publish = false [lib] crate-type = ["cdylib"] @@ -12,7 +9,7 @@ test = false doctest = false [dependencies] -oxc_resolver = { workspace = true } +oxc_resolver = { path = "../../oxc_resolver" } napi = { version = "2", features = ["serde-json", "async"] } napi-derive = { version = "2" } diff --git a/napi/index.d.ts b/napi/index.d.ts index 320e26ac..fb1848f7 100644 --- a/napi/index.d.ts +++ b/napi/index.d.ts @@ -3,12 +3,202 @@ /* auto-generated by NAPI-RS */ +/** + * Module Resolution Options + * + * Options are directly ported from [enhanced-resolve](https://github.com/webpack/enhanced-resolve#resolver-options). + * + * See [webpack resolve](https://webpack.js.org/configuration/resolve/) for information and examples + */ +export interface NapiResolveOptions { + /** + * Path to TypeScript configuration file. + * + * Default `None` + */ + tsconfig?: TsconfigOptions + /** + * Alias for [ResolveOptions::alias] and [ResolveOptions::fallback]. + * For the second value of the tuple, `None -> AliasValue::Ignore`, Some(String) -> + * AliasValue::Path(String)` + * Create aliases to import or require certain modules more easily. + * A trailing $ can also be added to the given object's keys to signify an exact match. + * + */ + alias?: Record> + /** + * A list of alias fields in description files. + * Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec). + * Can be a path to json object such as `["path", "to", "exports"]`. + * + * Default `[]` + */ + aliasFields?: Array> + /** + * Condition names for exports field which defines entry points of a package. + * The key order in the exports field is significant. During condition matching, earlier entries have higher priority and take precedence over later entries. + * + * Default `[]` + */ + conditionNames?: Array + /** + * The JSON files to use for descriptions. (There was once a `bower.json`.) + * + * Default `["package.json"]` + */ + descriptionFiles?: Array + /** + * If true, it will not allow extension-less files. + * So by default `require('./foo')` works if `./foo` has a `.js` extension, + * but with this enabled only `require('./foo.js')` will work. + * + * Default to `true` when [ResolveOptions::extensions] contains an empty string. + * Use `Some(false)` to disable the behavior. + * See + * + * Default None, which is the same as `Some(false)` when the above empty rule is not applied. + */ + enforceExtension?: EnforceExtension + /** + * A list of exports fields in description files. + * Can be a path to json object such as `["path", "to", "exports"]`. + * + * Default `[["exports"]]`. + */ + exportsFields?: Array> + /** + * An object which maps extension to extension aliases. + * + * Default `{}` + */ + extensionAlias?: Record> + /** + * Attempt to resolve these extensions in order. + * If multiple files share the same name but have different extensions, + * will resolve the one with the extension listed first in the array and skip the rest. + * + * Default `[".js", ".json", ".node"]` + */ + extensions?: Array + /** + * Redirect module requests when normal resolving fails. + * + * Default `[]` + */ + fallback?: Record> + /** + * Request passed to resolve is already fully specified and extensions or main files are not resolved for it (they are still resolved for internal requests). + * + * See also webpack configuration [resolve.fullySpecified](https://webpack.js.org/configuration/module/#resolvefullyspecified) + * + * Default `false` + */ + fullySpecified?: boolean + /** + * A list of main fields in description files + * + * Default `["main"]`. + */ + mainFields?: Array + /** + * The filename to be used while resolving directories. + * + * Default `["index"]` + */ + mainFiles?: Array + /** + * A list of directories to resolve modules from, can be absolute path or folder name. + * + * Default `["node_modules"]` + */ + modules?: Array + /** + * Resolve to a context instead of a file. + * + * Default `false` + */ + resolveToContext?: boolean + /** + * Prefer to resolve module requests as relative requests instead of using modules from node_modules directories. + * + * Default `false` + */ + preferRelative?: boolean + /** + * Prefer to resolve server-relative urls as absolute paths before falling back to resolve in ResolveOptions::roots. + * + * Default `false` + */ + preferAbsolute?: boolean + /** + * A list of resolve restrictions to restrict the paths that a request can be resolved on. + * + * Default `[]` + */ + restrictions?: Array + /** + * A list of directories where requests of server-relative URLs (starting with '/') are resolved. + * On non-Windows systems these requests are resolved as an absolute path first. + * + * Default `[]` + */ + roots?: Array + /** + * Whether to resolve symlinks to their symlinked location. + * When enabled, symlinked resources are resolved to their real path, not their symlinked location. + * Note that this may cause module resolution to fail when using tools that symlink packages (like npm link). + * + * Default `true` + */ + symlinks?: boolean + /** + * Whether to parse [module.builtinModules](https://nodejs.org/api/module.html#modulebuiltinmodules) or not. + * For example, "zlib" will throw [crate::ResolveError::Builtin] when set to true. + * + * Default `false` + */ + builtinModules?: boolean +} +export const enum EnforceExtension { + Auto = 0, + Enabled = 1, + Disabled = 2 +} +/** + * Alias Value for [ResolveOptions::alias] and [ResolveOptions::fallback]. + * Use struct because napi don't support structured union now + */ +export interface Restriction { + path?: string + regex?: string +} +/** + * Tsconfig Options + * + * Derived from [tsconfig-paths-webpack-plugin](https://github.com/dividab/tsconfig-paths-webpack-plugin#options) + */ +export interface TsconfigOptions { + /** + * Allows you to specify where to find the TypeScript configuration file. + * You may provide + * * a relative path to the configuration file. It will be resolved relative to cwd. + * * an absolute path to the configuration file. + */ + configFile: string + /** + * Support for Typescript Project References. + * For the type TsconfigReferences + * + */ + references: 'disabled'| 'auto' | 'Array' +} export interface ResolveResult { path?: string error?: string } export function sync(path: string, request: string): ResolveResult export class ResolverFactory { - constructor() + constructor(op: NapiResolveOptions) + static default(): ResolverFactory sync(path: string, request: string): ResolveResult } diff --git a/napi/index.js b/napi/index.js index 90128b73..9e9e21f4 100644 --- a/napi/index.js +++ b/napi/index.js @@ -252,7 +252,8 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { ResolverFactory, sync } = nativeBinding +const { EnforceExtension, ResolverFactory, sync } = nativeBinding +module.exports.EnforceExtension = EnforceExtension module.exports.ResolverFactory = ResolverFactory module.exports.sync = sync diff --git a/napi/package.json b/napi/package.json index 9847d80f..5681566c 100644 --- a/napi/package.json +++ b/napi/package.json @@ -3,6 +3,7 @@ "private": true, "scripts": { "build": "napi build --platform --release", + "build:debug": "napi build --platform ", "test": "node test.mjs" }, "devDependencies": { diff --git a/napi/src/lib.rs b/napi/src/lib.rs index b90092cc..e3354183 100644 --- a/napi/src/lib.rs +++ b/napi/src/lib.rs @@ -1,9 +1,16 @@ +extern crate napi; +extern crate napi_derive; +extern crate oxc_resolver; + use std::path::{Path, PathBuf}; use napi_derive::napi; - use oxc_resolver::{ResolveOptions, Resolver}; +use self::options::NapiResolveOptions; + +mod options; + #[napi(object)] pub struct ResolveResult { pub path: Option, @@ -15,17 +22,92 @@ pub struct ResolverFactory { resolver: Resolver, } -impl Default for ResolverFactory { - fn default() -> Self { - Self::new() - } -} - #[napi] impl ResolverFactory { #[napi(constructor)] - pub fn new() -> Self { - Self { resolver: Resolver::new(ResolveOptions::default()) } + pub fn new(op: NapiResolveOptions) -> Self { + let default_options = ResolveOptions::default(); + // merging options + let finalize_options = ResolveOptions { + tsconfig: op.tsconfig.map(|tsconfig| tsconfig.into()), + alias: op + .alias + .map(|alias| { + alias + .into_iter() + .map(|(k, v)| { + let v = v + .into_iter() + .map(|item| match item { + Some(path) => oxc_resolver::AliasValue::Path(path), + None => oxc_resolver::AliasValue::Ignore, + }) + .collect(); + (k, v) + }) + .collect::>() + }) + .unwrap_or(default_options.alias), + alias_fields: op.alias_fields.unwrap_or(default_options.alias_fields), + condition_names: op.condition_names.unwrap_or(default_options.condition_names), + description_files: op.description_files.unwrap_or(default_options.description_files), + enforce_extension: op + .enforce_extension + .map(|enforce_extension| enforce_extension.into()) + .unwrap_or(default_options.enforce_extension), + exports_fields: op.exports_fields.unwrap_or(default_options.exports_fields), + extension_alias: op + .extension_alias + .map(|extension_alias| extension_alias.into_iter().collect::>()) + .unwrap_or(default_options.extension_alias), + extensions: op.extensions.unwrap_or(default_options.extensions), + fallback: op + .fallback + .map(|fallback| { + fallback + .into_iter() + .map(|(k, v)| { + let v = v + .into_iter() + .map(|item| match item { + Some(path) => oxc_resolver::AliasValue::Path(path), + None => oxc_resolver::AliasValue::Ignore, + }) + .collect(); + (k, v) + }) + .collect::>() + }) + .unwrap_or(default_options.fallback), + fully_specified: op.fully_specified.unwrap_or(default_options.fully_specified), + main_fields: op.main_fields.unwrap_or(default_options.main_fields), + main_files: op.main_files.unwrap_or(default_options.main_files), + modules: op.modules.unwrap_or(default_options.modules), + resolve_to_context: op.resolve_to_context.unwrap_or(default_options.resolve_to_context), + prefer_relative: op.prefer_relative.unwrap_or(default_options.prefer_relative), + prefer_absolute: op.prefer_absolute.unwrap_or(default_options.prefer_absolute), + restrictions: op + .restrictions + .map(|restrictions| { + restrictions + .into_iter() + .map(|restriction| restriction.into()) + .collect::>() + }) + .unwrap_or(default_options.restrictions), + roots: op + .roots + .map(|roots| roots.into_iter().map(PathBuf::from).collect::>()) + .unwrap_or(default_options.roots), + symlinks: op.symlinks.unwrap_or(default_options.symlinks), + builtin_modules: op.builtin_modules.unwrap_or(default_options.builtin_modules), + }; + Self { resolver: Resolver::new(finalize_options) } + } + #[napi] + pub fn default() -> Self { + let default_options = ResolveOptions::default(); + Self { resolver: Resolver::new(default_options) } } #[allow(clippy::needless_pass_by_value)] diff --git a/napi/src/options.rs b/napi/src/options.rs new file mode 100644 index 00000000..cc379aff --- /dev/null +++ b/napi/src/options.rs @@ -0,0 +1,236 @@ +use std::path::PathBuf; + +use napi::Either; +use napi_derive::napi; +use std::collections::HashMap; + +/// Module Resolution Options +/// +/// Options are directly ported from [enhanced-resolve](https://github.com/webpack/enhanced-resolve#resolver-options). +/// +/// See [webpack resolve](https://webpack.js.org/configuration/resolve/) for information and examples +#[derive(Debug, Clone)] +#[napi(object)] +pub struct NapiResolveOptions { + /// Path to TypeScript configuration file. + /// + /// Default `None` + pub tsconfig: Option, + + /// Alias for [ResolveOptions::alias] and [ResolveOptions::fallback]. + /// For the second value of the tuple, `None -> AliasValue::Ignore`, Some(String) -> + /// AliasValue::Path(String)` + /// Create aliases to import or require certain modules more easily. + /// A trailing $ can also be added to the given object's keys to signify an exact match. + /// + pub alias: Option>>>, + + /// A list of alias fields in description files. + /// Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec). + /// Can be a path to json object such as `["path", "to", "exports"]`. + /// + /// Default `[]` + pub alias_fields: Option>>, + + /// Condition names for exports field which defines entry points of a package. + /// The key order in the exports field is significant. During condition matching, earlier entries have higher priority and take precedence over later entries. + /// + /// Default `[]` + pub condition_names: Option>, + + /// The JSON files to use for descriptions. (There was once a `bower.json`.) + /// + /// Default `["package.json"]` + pub description_files: Option>, + + /// If true, it will not allow extension-less files. + /// So by default `require('./foo')` works if `./foo` has a `.js` extension, + /// but with this enabled only `require('./foo.js')` will work. + /// + /// Default to `true` when [ResolveOptions::extensions] contains an empty string. + /// Use `Some(false)` to disable the behavior. + /// See + /// + /// Default None, which is the same as `Some(false)` when the above empty rule is not applied. + pub enforce_extension: Option, + + /// A list of exports fields in description files. + /// Can be a path to json object such as `["path", "to", "exports"]`. + /// + /// Default `[["exports"]]`. + pub exports_fields: Option>>, + + /// An object which maps extension to extension aliases. + /// + /// Default `{}` + pub extension_alias: Option>>, + + /// Attempt to resolve these extensions in order. + /// If multiple files share the same name but have different extensions, + /// will resolve the one with the extension listed first in the array and skip the rest. + /// + /// Default `[".js", ".json", ".node"]` + pub extensions: Option>, + + /// Redirect module requests when normal resolving fails. + /// + /// Default `[]` + pub fallback: Option>>>, + + /// Request passed to resolve is already fully specified and extensions or main files are not resolved for it (they are still resolved for internal requests). + /// + /// See also webpack configuration [resolve.fullySpecified](https://webpack.js.org/configuration/module/#resolvefullyspecified) + /// + /// Default `false` + pub fully_specified: Option, + + /// A list of main fields in description files + /// + /// Default `["main"]`. + pub main_fields: Option>, + + /// The filename to be used while resolving directories. + /// + /// Default `["index"]` + pub main_files: Option>, + + /// A list of directories to resolve modules from, can be absolute path or folder name. + /// + /// Default `["node_modules"]` + pub modules: Option>, + + /// Resolve to a context instead of a file. + /// + /// Default `false` + pub resolve_to_context: Option, + + /// Prefer to resolve module requests as relative requests instead of using modules from node_modules directories. + /// + /// Default `false` + pub prefer_relative: Option, + + /// Prefer to resolve server-relative urls as absolute paths before falling back to resolve in ResolveOptions::roots. + /// + /// Default `false` + pub prefer_absolute: Option, + + /// A list of resolve restrictions to restrict the paths that a request can be resolved on. + /// + /// Default `[]` + pub restrictions: Option>, + + /// A list of directories where requests of server-relative URLs (starting with '/') are resolved. + /// On non-Windows systems these requests are resolved as an absolute path first. + /// + /// Default `[]` + pub roots: Option>, + + /// Whether to resolve symlinks to their symlinked location. + /// When enabled, symlinked resources are resolved to their real path, not their symlinked location. + /// Note that this may cause module resolution to fail when using tools that symlink packages (like npm link). + /// + /// Default `true` + pub symlinks: Option, + + /// Whether to parse [module.builtinModules](https://nodejs.org/api/module.html#modulebuiltinmodules) or not. + /// For example, "zlib" will throw [crate::ResolveError::Builtin] when set to true. + /// + /// Default `false` + pub builtin_modules: Option, +} + +#[napi] +#[derive(Debug, PartialEq, Eq)] +pub enum EnforceExtension { + Auto, + Enabled, + Disabled, +} + +impl EnforceExtension { + pub fn is_auto(&self) -> bool { + *self == Self::Auto + } + + pub fn is_enabled(&self) -> bool { + *self == Self::Enabled + } + + pub fn is_disabled(&self) -> bool { + *self == Self::Disabled + } +} + +/// Alias Value for [ResolveOptions::alias] and [ResolveOptions::fallback]. +/// Use struct because napi don't support structured union now +#[napi(object)] +#[derive(Debug, Clone)] +pub struct Restriction { + pub path: Option, + pub regex: Option, +} + +/// Tsconfig Options +/// +/// Derived from [tsconfig-paths-webpack-plugin](https://github.com/dividab/tsconfig-paths-webpack-plugin#options) +#[napi(object)] +#[derive(Debug, Clone)] +pub struct TsconfigOptions { + /// Allows you to specify where to find the TypeScript configuration file. + /// You may provide + /// * a relative path to the configuration file. It will be resolved relative to cwd. + /// * an absolute path to the configuration file. + pub config_file: String, + /// Support for Typescript Project References. + /// For the type TsconfigReferences + /// + #[napi(ts_type = "'disabled'| 'auto' | 'Array'")] + pub references: Either>, +} + +impl Into for Restriction { + fn into(self) -> oxc_resolver::Restriction { + match (self.path, self.regex) { + (None, None) => { + panic!("Should specify path or regex") + } + (None, Some(regex)) => oxc_resolver::Restriction::RegExp(regex), + (Some(path), None) => oxc_resolver::Restriction::Path(PathBuf::from(path)), + (Some(_), Some(_)) => { + panic!("Restriction can't be path and regex at the same time") + } + } + } +} + +impl Into for EnforceExtension { + fn into(self) -> oxc_resolver::EnforceExtension { + match self { + EnforceExtension::Auto => oxc_resolver::EnforceExtension::Auto, + EnforceExtension::Enabled => oxc_resolver::EnforceExtension::Enabled, + EnforceExtension::Disabled => oxc_resolver::EnforceExtension::Disabled, + } + } +} + +impl Into for TsconfigOptions { + fn into(self) -> oxc_resolver::TsconfigOptions { + oxc_resolver::TsconfigOptions { + config_file: PathBuf::from(self.config_file), + references: match self.references { + Either::A(string) if string.as_str() == "disabled" => { + oxc_resolver::TsconfigReferences::Disabled + } + Either::A(string) if string.as_str() == "auto" => { + oxc_resolver::TsconfigReferences::Auto + } + Either::A(opt) => { + panic!("`{}` is not a valid option for tsconfig references", opt) + } + Either::B(paths) => oxc_resolver::TsconfigReferences::Paths( + paths.into_iter().map(PathBuf::from).collect::>(), + ), + }, + } + } +} diff --git a/napi/test.mjs b/napi/test.mjs index 924d64c1..56a2aa0a 100644 --- a/napi/test.mjs +++ b/napi/test.mjs @@ -7,8 +7,22 @@ console.log(`Testing on ${process.platform}-${process.arch}`) const cwd = process.cwd(); // `resolve` -assert(resolve.sync(cwd, "./index.js").path, path.join(cwd, 'index.js')); +assert.deepStrictEqual(resolve.sync(cwd, "./index.js").path, path.join(cwd, 'index.js')); // `ResolverFactory` -const resolver = new ResolverFactory(); -assert(resolver.sync(cwd, "./index.js").path, path.join(cwd, 'index.js')); +const resolver = ResolverFactory.default(); +assert.deepStrictEqual(resolver.sync(cwd, "./index.js").path, path.join(cwd, 'index.js')); + +assert.strict(resolver.sync(cwd, "./ts").error.length > 0); + + +// custom constructor +const resolver2 = new ResolverFactory( + { + extensions: ['.mjs'] + } +); + +// After add `.ts` extension, resolver can resolve `ts` as `ts.ts` now +assert.deepStrictEqual(resolver2.sync(cwd, "./test.mjs").path, path.join(cwd, 'test.mjs')); +