Comparing version 0.1.2 to 0.2.0
@@ -21,3 +21,3 @@ import * as bundle_require from 'bundle-require'; | ||
* | ||
* @see https://tsx.is/node#tsimport | ||
* @see https://tsx.is/node/ts-import | ||
*/ | ||
@@ -54,7 +54,6 @@ tsx?: Omit<Partial<Exclude<ArgumentTypes<typeof tsx_esm_api.tsImport>['1'], string>>, 'parentURL'>; | ||
* `cache: true` does not compatible with following loaders: | ||
* - `tsx` | ||
* - `bundle-require` | ||
* | ||
* When `false` is passed, the `auto` mode will fallback to `tsx` | ||
* for all files include non-TypeScript files. | ||
* Affects `auto` resolution: | ||
* - When set to `false`, `native` will be fallback to `tsx` or `jiti` | ||
* | ||
@@ -65,2 +64,13 @@ * @default null | ||
/** | ||
* List dependencies of the module. | ||
* | ||
* Only available for `tsx` and `bundle-require` loader. | ||
* | ||
* Affects `auto` resolution: | ||
* - When set to `true`, `jiti` will be fallback to `bundle-require` | ||
* | ||
* @default false | ||
*/ | ||
listDependencies?: boolean; | ||
/** | ||
* Bypass the `importx` options validation and import anyway. | ||
@@ -98,2 +108,10 @@ * | ||
/** | ||
* Resolved full path the specifier points to. | ||
*/ | ||
fullPath: string; | ||
/** | ||
* Enable module cache or not | ||
*/ | ||
cache: boolean | null; | ||
/** | ||
* Parent URL, normalized to file URL. | ||
@@ -100,0 +118,0 @@ */ |
{ | ||
"name": "importx", | ||
"type": "module", | ||
"version": "0.1.2", | ||
"packageManager": "pnpm@9.0.2", | ||
"version": "0.2.0", | ||
"packageManager": "pnpm@9.1.0", | ||
"description": "Unified tool for importing TypeScript modules at runtime", | ||
@@ -57,19 +57,18 @@ "author": "Anthony Fu <anthonyfu117@hotmail.com>", | ||
"jiti": "^1.21.0", | ||
"tsx": "^4.9.4" | ||
"tsx": "^4.10.0" | ||
}, | ||
"devDependencies": { | ||
"@antfu/eslint-config": "^2.14.0", | ||
"@antfu/eslint-config": "^2.17.0", | ||
"@antfu/ni": "^0.21.12", | ||
"@antfu/utils": "^0.7.7", | ||
"@antfu/utils": "^0.7.8", | ||
"@types/debug": "^4.1.12", | ||
"@types/node": "^20.12.7", | ||
"bumpp": "^9.4.0", | ||
"eslint": "^9.0.0", | ||
"@types/node": "^20.12.11", | ||
"bumpp": "^9.4.1", | ||
"eslint": "^9.2.0", | ||
"esno": "^4.7.0", | ||
"execa": "^9.0.2", | ||
"lint-staged": "^15.2.2", | ||
"ms": "^2.1.3", | ||
"picocolors": "^1.0.0", | ||
"pnpm": "^9.0.2", | ||
"rimraf": "^5.0.5", | ||
"pnpm": "^9.1.0", | ||
"rimraf": "^5.0.6", | ||
"simple-git-hooks": "^2.11.1", | ||
@@ -79,4 +78,4 @@ "ts-node": "^10.9.2", | ||
"unbuild": "^2.0.0", | ||
"vite": "^5.2.9", | ||
"vitest": "^1.5.0" | ||
"vite": "^5.2.11", | ||
"vitest": "^1.6.0" | ||
}, | ||
@@ -83,0 +82,0 @@ "simple-git-hooks": { |
127
README.md
@@ -20,11 +20,6 @@ # importx | ||
There are so many ways to do that, each with its own trade-offs and limitations. This library aims to provide a simple, unified API for importing TypeScript modules, balancing out their limitations, providing an easy-to-use API, and making it easy to switch between different loaders. | ||
There are so many ways to do that, each with its own trade-offs and limitations. This library aims to provide a simple, unified API for importing TypeScript modules, providing an easy-to-use API, and making it easy to switch between different loaders. | ||
By default, it also provides a smart "auto" mode that decides the best loader based on the environment: | ||
By default, it also provides [a smart "auto" mode that decides the best loader based on the environment](#auto), trying to ease out their limitations and provide the best experience. The goal is for this library to swallow the complexity of the underlying implementations, where you can just focus on the feature set you need. This library will keep up-to-date with the latest loaders and the runtime environment. | ||
- Use native `import()` for runtimes that support directly importing TypeScript modules (Deno, Bun, or `ts-node`, `tsx` CLI). | ||
- Use `tsx` for modern module environments. | ||
- Use `jiti` for older Node.js that don't support `tsx`. | ||
- Use `bundle-require` when you want to import a module without the ESM cache. | ||
## Usage | ||
@@ -40,2 +35,18 @@ | ||
## Options | ||
You can turn the second argument of `import` into an object to provide options: | ||
```ts | ||
const mod = await import('importx').then(x => x.import('./path/to/module.ts', { | ||
parentURL: import.meta.url, // *required | ||
// The following options are their default values | ||
cache: null, // false, if you want to always get a new module | ||
listDependencies: false, // true, if you need to get the list of dependencies | ||
loader: 'auto', // most of the time, you don't need to change this as they will be chosen automatically | ||
})) | ||
``` | ||
## Loaders | ||
@@ -49,17 +60,30 @@ | ||
graph TD | ||
A((Auto)) --> IsTS{{"Is importing a TypeScript file?"}} | ||
IsTS --> |No| Cache{{"Import cache?"}} | ||
Cache --> |true,null| Native1(["native import()"]) | ||
Cache --> |false| F | ||
A((Auto)) --> Cache | ||
Cache2 --> |false| F | ||
IsTS --> |Yes| Cache2{{"Import cache?"}} | ||
Cache2 --> |true,null| D{{"Supports native TypeScript?"}} | ||
D --> |No| Cache3{{"Import cache?"}} | ||
D --> |Yes| Native2(["native import()"]) | ||
Cache3 --> |true| Jiti1([jiti]) | ||
Cache3 --> |null| F{{"Is current runtime supports tsx?"}} | ||
F --> |Yes| Tsx3([tsx]) | ||
F --> |No| Jiti2([jiti]) | ||
Cache --> |false| RuntimeTsx | ||
Cache --> |true / null| IsTS | ||
IsTS --> |Yes| SupportTs | ||
IsTS --> |No| Native1 | ||
SupportTs --> |No| RuntimeTsx | ||
SupportTs --> |Yes| Native2 | ||
RuntimeTsx --> |Yes| Tsx | ||
RuntimeTsx --> |No| ListDeps | ||
ListDeps --> |Yes| BundleRequire | ||
ListDeps --> |No| Jiti | ||
IsTS{{"Is importing a TypeScript file?"}} | ||
SupportTs{{"Supports native TypeScript?"}} | ||
Cache[["Cache enabled?"]] | ||
Native1(["native import()"]) | ||
Native2(["native import()"]) | ||
RuntimeTsx{{"Is current runtime supports tsx?"}} | ||
ListDeps[["Need to list dependencies?"]] | ||
Tsx([tsx loader]) | ||
Jiti([jiti loader]) | ||
BundleRequire([bundle-require loader]) | ||
classDef auto fill:#0f82,stroke:#0f83,stroke-width:2px; | ||
@@ -69,10 +93,14 @@ classDef question fill:#f9f2,stroke:#f9f3,stroke-width:2px; | ||
classDef native fill:#8882,stroke:#8883,stroke-width:2px; | ||
classDef tsx fill:#09f2,stroke:#09f3,stroke-width:2px; | ||
classDef ts fill:#09f2,stroke:#09f3,stroke-width:2px; | ||
classDef tsx fill:#0fe2,stroke:#0fe3,stroke-width:2px; | ||
classDef jiti fill:#ffde2220,stroke:#ffde2230,stroke-width:2px; | ||
classDef bundle fill:#5f32,stroke:#5f33,stroke-width:2px; | ||
class A auto; | ||
class IsTS,D,F question; | ||
class Cache,Cache2,Cache3 cache; | ||
class Native1,Native2 native; | ||
class Tsx1,Tsx2,Tsx3 tsx; | ||
class Jiti1,Jiti2 jiti; | ||
class RuntimeTsx question; | ||
class Cache,ListDeps cache; | ||
class Native1,Native2,Native3 native; | ||
class IsTS,SupportTs ts; | ||
class Tsx tsx; | ||
class Jiti jiti; | ||
class BundleRequire bundle; | ||
linkStyle default stroke:#8888 | ||
@@ -83,7 +111,7 @@ ``` | ||
Use the native `import()` to import the module. | ||
Use the native `import()` to import the module. According to the ESM spec, importing the same module multiple times will return the same module instance. | ||
### `tsx` | ||
Use [`tsx`](https://github.com/privatenumber/tsx)'s [`tsImport` API](https://tsx.is/node#tsimport) to import the module. Under the hood, it registers [Node.js loader API](https://nodejs.org/api/module.html#moduleregisterspecifier-parenturl-options) and uses [esbuild](https://esbuild.github.io/) to transpile TypeScript to JavaScript. | ||
Use [`tsx`](https://github.com/privatenumber/tsx)'s [`tsImport` API](https://tsx.is/node/ts-import) to import the module. Under the hood, it registers [Node.js loader API](https://nodejs.org/api/module.html#moduleregisterspecifier-parenturl-options) and uses [esbuild](https://esbuild.github.io/) to transpile TypeScript to JavaScript. | ||
@@ -94,6 +122,7 @@ #### Pros | ||
- Get the file list of module dependencies. Helpful for hot-reloading or manifest generation. | ||
- Supports [scoped registration](https://tsx.is/node/esm#scoped-registration), does not affect the global environment. | ||
#### Limitations | ||
- Requires Node.js `^18.18.0`, `^20.6.0` or above. | ||
- Requires Node.js `^18.18.0`, `^20.6.0` or above. Does not work on other runtime yet. | ||
@@ -106,4 +135,4 @@ ### `jiti` | ||
- Self-contained, does not dependents on esbuild. | ||
- Own cache and module runner, better and flexible cache control. | ||
- Self-contained, does not depend on esbuild. | ||
- Own cache and module runner, better and flexible cache control. Works on the majority of Node-compatible runtimes. | ||
@@ -125,4 +154,5 @@ #### Limitations | ||
- It creates a temporary bundle file on importing (will external `node_modules`). | ||
- It creates a temporary bundle file when importing (will external `node_modules`). | ||
- Can be inefficient where there are many TypeScript modules in the import tree. | ||
- Imports are using esbuild's resolution, which might have potential misalignment with Node.js. | ||
- Always import a new module, does not support module cache. | ||
@@ -178,2 +208,16 @@ | ||
## List Module Dependencies | ||
In cases like loading a config file for a dev server, where you need to watch for changes in the config file and reload the server, you may want to know the module's dependencies to watch for changes in them as well. | ||
`tsx` and `bundle-require` loaders support listing the dependencies of the module. You can get the list of dependencies by [getting the module info](#get-module-info). To ensure you use always have the dependencies list in `auto` mode, you can set the `listDependencies` option to `true`: | ||
```ts | ||
const mod = await import('importx') | ||
.then(x => x.import('./path/to/module.ts', { | ||
listDependencies: true, | ||
parentURL: import.meta.url, | ||
})) | ||
``` | ||
## Runtime-Loader Compatibility Table | ||
@@ -185,13 +229,22 @@ | ||
> Generated with version `v0.1.0` at 2024-05-11T12:28:48.832Z | ||
> Generated with version `v0.1.2` at 2024-05-11T19:12:27.740Z | ||
| | native | tsx | jiti | bundle-require | | ||
| ------- | --- | --- | --- | --- | | ||
| node | Import: ❌<br>Cache: ❌<br>No cache: ❌ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | Import: ✅<br>Cache: ✅<br>No cache: ✅ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | | ||
| tsx | Import: ✅<br>Cache: ✅<br>No cache: ❌ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | Import: ✅<br>Cache: ✅<br>No cache: ✅ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | | ||
| deno | Import: ✅<br>Cache: ✅<br>No cache: ❌ | Import: ❌<br>Cache: ❌<br>No cache: ❌ | Import: ✅<br>Cache: ✅<br>No cache: ✅ | Import: ❌<br>Cache: ❌<br>No cache: ❌ | | ||
| bun | Import: ✅<br>Cache: ✅<br>No cache: ❌ | Import: ❌<br>Cache: ❌<br>No cache: ❌ | Import: ✅<br>Cache: ✅<br>No cache: ❌ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | | ||
| node | Import: ❌<br>Cache: ❌<br>No cache: `N/A` | Import: ✅<br>Cache: ✅<br>No cache: ✅ | Import: ✅<br>Cache: ✅<br>No cache: ✅ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | | ||
| tsx | Import: ✅<br>Cache: ✅<br>No cache: `N/A` | Import: ✅<br>Cache: ✅<br>No cache: ✅ | Import: ✅<br>Cache: ✅<br>No cache: ✅ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | | ||
| deno | Import: ✅<br>Cache: ✅<br>No cache: `N/A` | Import: ❌<br>Cache: ❌<br>No cache: ❌ | Import: ✅<br>Cache: ✅<br>No cache: ✅ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | | ||
| bun | Import: ✅<br>Cache: ✅<br>No cache: `N/A` | Import: ❌<br>Cache: ❌<br>No cache: ❌ | Import: ✅<br>Cache: ✅<br>No cache: ❌ | Import: ✅<br>Cache: ❌<br>No cache: ✅ | | ||
<!-- TABLE_END --> | ||
## Features-Loader Table | ||
| | native | tsx | jiti | bundle-require | | ||
| --------------------------- | --- | --- | --- | --- | | ||
| Cache: `true` | ✅ | ✅ | ✅ | ❌ | | ||
| Cache: `false` | ❌ | ✅ | ✅ | ✅ | | ||
| List dependencies | ❌ | ✅ | ❌ | ✅ | | ||
| Runtimes other than Node.js | ✅ | ❌ | ✅ | ✅ | | ||
## Sponsors | ||
@@ -198,0 +251,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
29529
19
8
323
264
Updatedtsx@^4.10.0