@flightdev/loader 0.2.0
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/LICENSE +21 -0
- package/README.md +147 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.js +6 -0
- package/dist/register.js.map +1 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Flight Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# @flight-framework/loader
|
|
2
|
+
|
|
3
|
+
Optional ESM loader for TypeScript extension resolution in Node.js. This package enables seamless imports without explicit file extensions.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
This package is **optional**. Modern Node.js versions (22.18+) include native TypeScript support. Use this loader only if:
|
|
8
|
+
|
|
9
|
+
- You are on Node.js < 22.18
|
|
10
|
+
- You need custom extension resolution behavior
|
|
11
|
+
- You want consistent resolution across all Node.js versions
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @flight-framework/loader
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Option 1: Node.js Native TypeScript (Recommended)
|
|
22
|
+
|
|
23
|
+
Node.js v22.18+ includes native TypeScript type stripping:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# v22.18+ (enabled by default in v23.6+)
|
|
27
|
+
node --experimental-strip-types ./server.ts
|
|
28
|
+
|
|
29
|
+
# v25.2+ (stable, no flag needed)
|
|
30
|
+
node ./server.ts
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Option 2: Flight Loader
|
|
34
|
+
|
|
35
|
+
For older Node.js versions or custom resolution:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
node --import @flight-framework/loader/register ./server.js
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Option 3: tsconfig.json Configuration
|
|
42
|
+
|
|
43
|
+
Configure TypeScript to rewrite imports during compilation:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"compilerOptions": {
|
|
48
|
+
"module": "nodenext",
|
|
49
|
+
"moduleResolution": "nodenext",
|
|
50
|
+
"rewriteRelativeImportExtensions": true,
|
|
51
|
+
"erasableSyntaxOnly": true,
|
|
52
|
+
"verbatimModuleSyntax": true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The `rewriteRelativeImportExtensions` option (TypeScript 5.7+) rewrites `.ts` imports to `.js` in output.
|
|
58
|
+
|
|
59
|
+
## How It Works
|
|
60
|
+
|
|
61
|
+
The loader implements Node.js module customization hooks to:
|
|
62
|
+
|
|
63
|
+
1. **Resolve** - Find files without explicit extensions by trying `.ts`, `.tsx`, `.js`, etc.
|
|
64
|
+
2. **Load** - Pass TypeScript files to Node.js native type stripping (v22.18+)
|
|
65
|
+
|
|
66
|
+
### Extension Priority
|
|
67
|
+
|
|
68
|
+
When importing without an extension (e.g., `import { x } from './utils'`):
|
|
69
|
+
|
|
70
|
+
1. `./utils.ts`
|
|
71
|
+
2. `./utils.tsx`
|
|
72
|
+
3. `./utils.mts`
|
|
73
|
+
4. `./utils.js`
|
|
74
|
+
5. `./utils.jsx`
|
|
75
|
+
6. `./utils.mjs`
|
|
76
|
+
7. `./utils.json`
|
|
77
|
+
8. `./utils/index.ts`
|
|
78
|
+
9. `./utils/index.js`
|
|
79
|
+
|
|
80
|
+
## API
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import {
|
|
84
|
+
supportsNativeTypeScript,
|
|
85
|
+
getRecommendedFlags,
|
|
86
|
+
resolveWithExtensions,
|
|
87
|
+
RESOLVE_EXTENSIONS
|
|
88
|
+
} from '@flight-framework/loader';
|
|
89
|
+
|
|
90
|
+
// Check Node.js capability
|
|
91
|
+
if (supportsNativeTypeScript()) {
|
|
92
|
+
// Node.js can handle TypeScript natively
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Get recommended CLI flags
|
|
96
|
+
const flags = getRecommendedFlags();
|
|
97
|
+
// ['--experimental-strip-types'] or [] for v25+
|
|
98
|
+
|
|
99
|
+
// Resolve specifier with extensions
|
|
100
|
+
const paths = resolveWithExtensions('./utils');
|
|
101
|
+
// ['./utils.ts', './utils.tsx', './utils.mts', ...]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Bundler Integration
|
|
105
|
+
|
|
106
|
+
Flight's bundlers (Vite, esbuild, Rolldown) include automatic extension resolution. This loader is only needed for runtime Node.js execution outside of the bundler.
|
|
107
|
+
|
|
108
|
+
### Vite
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// Automatic - resolve.extensions is configured by default
|
|
112
|
+
import { defineConfig } from '@flight-framework/core';
|
|
113
|
+
import { vite } from '@flight-framework/bundler-vite';
|
|
114
|
+
|
|
115
|
+
export default defineConfig({
|
|
116
|
+
bundler: vite(),
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### esbuild
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// Automatic - resolveExtensions is configured by default
|
|
124
|
+
import { esbuild } from '@flight-framework/bundler-esbuild';
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Rolldown
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Automatic - resolve.extensions is configured by default
|
|
131
|
+
import { rolldown } from '@flight-framework/bundler-rolldown';
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Requirements
|
|
135
|
+
|
|
136
|
+
- Node.js >= 20.0.0
|
|
137
|
+
- For native TypeScript: Node.js >= 22.18.0
|
|
138
|
+
|
|
139
|
+
## Related
|
|
140
|
+
|
|
141
|
+
- [Module Resolution Guide](../../docs/module-resolution.md)
|
|
142
|
+
- [RSC Boundaries](../../docs/rsc-boundaries.md)
|
|
143
|
+
- [TypeScript Configuration](../../docs/typescript.md)
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESM Loader Hooks for Node.js
|
|
3
|
+
*
|
|
4
|
+
* These hooks implement the Node.js module customization API
|
|
5
|
+
* to resolve TypeScript extensions automatically.
|
|
6
|
+
*
|
|
7
|
+
* @see https://nodejs.org/api/module.html#customization-hooks
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Context passed to the resolve hook
|
|
11
|
+
*/
|
|
12
|
+
interface ResolveContext {
|
|
13
|
+
conditions: string[];
|
|
14
|
+
importAttributes: Record<string, string>;
|
|
15
|
+
parentURL?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Result from the resolve hook
|
|
19
|
+
*/
|
|
20
|
+
interface ResolveResult {
|
|
21
|
+
url: string;
|
|
22
|
+
format?: 'builtin' | 'commonjs' | 'json' | 'module' | 'wasm';
|
|
23
|
+
shortCircuit?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Context passed to the load hook
|
|
27
|
+
*/
|
|
28
|
+
interface LoadContext {
|
|
29
|
+
conditions: string[];
|
|
30
|
+
format?: string;
|
|
31
|
+
importAttributes: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Result from the load hook
|
|
35
|
+
*/
|
|
36
|
+
interface LoadResult {
|
|
37
|
+
format: 'builtin' | 'commonjs' | 'json' | 'module' | 'wasm';
|
|
38
|
+
source?: string | ArrayBuffer | SharedArrayBuffer;
|
|
39
|
+
shortCircuit?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @flightdev/loader
|
|
44
|
+
*
|
|
45
|
+
* Optional ESM loader for TypeScript extension resolution in Node.js.
|
|
46
|
+
* This package provides automatic resolution of TypeScript file extensions
|
|
47
|
+
* for transitive imports when running in Node.js ESM mode.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```bash
|
|
51
|
+
* # Option 1: Use Node.js native TypeScript (v22.18+, recommended)
|
|
52
|
+
* node --experimental-strip-types ./server.ts
|
|
53
|
+
*
|
|
54
|
+
* # Option 2: Use Flight loader for older Node.js or custom resolution
|
|
55
|
+
* node --import @flightdev/loader/register ./server.js
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* TypeScript file extensions that will be resolved automatically
|
|
60
|
+
*/
|
|
61
|
+
declare const TYPESCRIPT_EXTENSIONS: readonly [".ts", ".tsx", ".mts", ".cts"];
|
|
62
|
+
/**
|
|
63
|
+
* All resolvable extensions in order of priority
|
|
64
|
+
*/
|
|
65
|
+
declare const RESOLVE_EXTENSIONS: readonly [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".json"];
|
|
66
|
+
/**
|
|
67
|
+
* Check if Node.js version supports native TypeScript stripping
|
|
68
|
+
*/
|
|
69
|
+
declare function supportsNativeTypeScript(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Get recommended Node.js flags for TypeScript execution
|
|
72
|
+
*/
|
|
73
|
+
declare function getRecommendedFlags(): string[];
|
|
74
|
+
/**
|
|
75
|
+
* Resolve a specifier with TypeScript extension fallbacks
|
|
76
|
+
*/
|
|
77
|
+
declare function resolveWithExtensions(specifier: string, extensions?: readonly string[]): string[];
|
|
78
|
+
|
|
79
|
+
export { type LoadContext, type LoadResult, RESOLVE_EXTENSIONS, type ResolveContext, type ResolveResult, TYPESCRIPT_EXTENSIONS, getRecommendedFlags, resolveWithExtensions, supportsNativeTypeScript };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var TYPESCRIPT_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts"];
|
|
3
|
+
var RESOLVE_EXTENSIONS = [
|
|
4
|
+
".ts",
|
|
5
|
+
".tsx",
|
|
6
|
+
".mts",
|
|
7
|
+
".cts",
|
|
8
|
+
".js",
|
|
9
|
+
".jsx",
|
|
10
|
+
".mjs",
|
|
11
|
+
".cjs",
|
|
12
|
+
".json"
|
|
13
|
+
];
|
|
14
|
+
function supportsNativeTypeScript() {
|
|
15
|
+
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
16
|
+
return major === 22 && minor >= 18 || major >= 23;
|
|
17
|
+
}
|
|
18
|
+
function getRecommendedFlags() {
|
|
19
|
+
if (supportsNativeTypeScript()) {
|
|
20
|
+
const [major] = process.versions.node.split(".").map(Number);
|
|
21
|
+
if (major >= 25 || major === 23 && parseInt(process.versions.node.split(".")[1]) >= 6) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
return ["--experimental-strip-types"];
|
|
25
|
+
}
|
|
26
|
+
return ["--import", "@flightdev/loader/register"];
|
|
27
|
+
}
|
|
28
|
+
function resolveWithExtensions(specifier, extensions = RESOLVE_EXTENSIONS) {
|
|
29
|
+
if (extensions.some((ext) => specifier.endsWith(ext))) {
|
|
30
|
+
return [specifier];
|
|
31
|
+
}
|
|
32
|
+
return extensions.map((ext) => `${specifier}${ext}`);
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
RESOLVE_EXTENSIONS,
|
|
36
|
+
TYPESCRIPT_EXTENSIONS,
|
|
37
|
+
getRecommendedFlags,
|
|
38
|
+
resolveWithExtensions,
|
|
39
|
+
supportsNativeTypeScript
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * @flightdev/loader\r\n * \r\n * Optional ESM loader for TypeScript extension resolution in Node.js.\r\n * This package provides automatic resolution of TypeScript file extensions\r\n * for transitive imports when running in Node.js ESM mode.\r\n * \r\n * @example\r\n * ```bash\r\n * # Option 1: Use Node.js native TypeScript (v22.18+, recommended)\r\n * node --experimental-strip-types ./server.ts\r\n * \r\n * # Option 2: Use Flight loader for older Node.js or custom resolution\r\n * node --import @flightdev/loader/register ./server.js\r\n * ```\r\n */\r\n\r\n/**\r\n * TypeScript file extensions that will be resolved automatically\r\n */\r\nexport const TYPESCRIPT_EXTENSIONS = ['.ts', '.tsx', '.mts', '.cts'] as const;\r\n\r\n/**\r\n * All resolvable extensions in order of priority\r\n */\r\nexport const RESOLVE_EXTENSIONS = [\r\n '.ts',\r\n '.tsx',\r\n '.mts',\r\n '.cts',\r\n '.js',\r\n '.jsx',\r\n '.mjs',\r\n '.cjs',\r\n '.json',\r\n] as const;\r\n\r\n/**\r\n * Check if Node.js version supports native TypeScript stripping\r\n */\r\nexport function supportsNativeTypeScript(): boolean {\r\n const [major, minor] = process.versions.node.split('.').map(Number);\r\n // Node.js v22.18+ has stable type stripping (enabled by default in v23.6+)\r\n return (major === 22 && minor >= 18) || major >= 23;\r\n}\r\n\r\n/**\r\n * Get recommended Node.js flags for TypeScript execution\r\n */\r\nexport function getRecommendedFlags(): string[] {\r\n if (supportsNativeTypeScript()) {\r\n const [major] = process.versions.node.split('.').map(Number);\r\n // v23.6+ and v25.2+ have it enabled by default\r\n if (major >= 25 || (major === 23 && parseInt(process.versions.node.split('.')[1]) >= 6)) {\r\n return []; // No flags needed\r\n }\r\n return ['--experimental-strip-types'];\r\n }\r\n return ['--import', '@flightdev/loader/register'];\r\n}\r\n\r\n/**\r\n * Resolve a specifier with TypeScript extension fallbacks\r\n */\r\nexport function resolveWithExtensions(\r\n specifier: string,\r\n extensions: readonly string[] = RESOLVE_EXTENSIONS\r\n): string[] {\r\n // If specifier already has an extension, return as-is\r\n if (extensions.some(ext => specifier.endsWith(ext))) {\r\n return [specifier];\r\n }\r\n\r\n // Generate possible paths with extensions\r\n return extensions.map(ext => `${specifier}${ext}`);\r\n}\r\n\r\nexport type { ResolveContext, LoadContext, ResolveResult, LoadResult } from './hooks';\r\n"],"mappings":";AAoBO,IAAM,wBAAwB,CAAC,OAAO,QAAQ,QAAQ,MAAM;AAK5D,IAAM,qBAAqB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAKO,SAAS,2BAAoC;AAChD,QAAM,CAAC,OAAO,KAAK,IAAI,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,IAAI,MAAM;AAElE,SAAQ,UAAU,MAAM,SAAS,MAAO,SAAS;AACrD;AAKO,SAAS,sBAAgC;AAC5C,MAAI,yBAAyB,GAAG;AAC5B,UAAM,CAAC,KAAK,IAAI,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,IAAI,MAAM;AAE3D,QAAI,SAAS,MAAO,UAAU,MAAM,SAAS,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,GAAI;AACrF,aAAO,CAAC;AAAA,IACZ;AACA,WAAO,CAAC,4BAA4B;AAAA,EACxC;AACA,SAAO,CAAC,YAAY,4BAA4B;AACpD;AAKO,SAAS,sBACZ,WACA,aAAgC,oBACxB;AAER,MAAI,WAAW,KAAK,SAAO,UAAU,SAAS,GAAG,CAAC,GAAG;AACjD,WAAO,CAAC,SAAS;AAAA,EACrB;AAGA,SAAO,WAAW,IAAI,SAAO,GAAG,SAAS,GAAG,GAAG,EAAE;AACrD;","names":[]}
|
package/dist/register.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/register.ts"],"sourcesContent":["/**\r\n * Auto-registration entry point for Node.js --import flag\r\n * \r\n * @example\r\n * ```bash\r\n * node --import @flightdev/loader/register ./server.js\r\n * ```\r\n */\r\n\r\nimport { register } from 'node:module';\r\nimport { pathToFileURL } from 'node:url';\r\n\r\n// Register the hooks\r\nregister('./hooks.js', pathToFileURL(import.meta.url));\r\n\r\nconsole.log('[Flight Loader] TypeScript extension resolution enabled');\r\n"],"mappings":";AASA,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAG9B,SAAS,cAAc,cAAc,YAAY,GAAG,CAAC;AAErD,QAAQ,IAAI,yDAAyD;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flightdev/loader",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Optional ESM loader for TypeScript extension resolution in Node.js",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"flight",
|
|
7
|
+
"framework",
|
|
8
|
+
"loader",
|
|
9
|
+
"esm",
|
|
10
|
+
"typescript"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Flight Contributors",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./register": {
|
|
21
|
+
"types": "./dist/register.d.ts",
|
|
22
|
+
"import": "./dist/register.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.0.0",
|
|
32
|
+
"rimraf": "^6.0.0",
|
|
33
|
+
"tsup": "^8.0.0",
|
|
34
|
+
"typescript": "^5.7.0"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=20.0.0"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"dev": "tsup --watch",
|
|
42
|
+
"clean": "rimraf dist",
|
|
43
|
+
"typecheck": "tsc --noEmit"
|
|
44
|
+
}
|
|
45
|
+
}
|