Skip to content

Commit b314da9

Browse files
committed
feat: support loading TypeScript files
1 parent 642c451 commit b314da9

16 files changed

+125
-4
lines changed

dist/get-env-vars.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getRCFileVars } from './parse-rc-file.js';
22
import { getEnvFileVars } from './parse-env-file.js';
3+
import { isLoaderError } from './utils.js';
34
const RC_FILE_DEFAULT_LOCATIONS = ['./.env-cmdrc', './.env-cmdrc.js', './.env-cmdrc.json'];
45
const ENV_FILE_DEFAULT_LOCATIONS = ['./.env', './.env.js', './.env.json'];
56
export async function getEnvVars(options = {}) {
@@ -28,7 +29,10 @@ export async function getEnvFile({ filePath, fallback, verbose }) {
2829
}
2930
return env;
3031
}
31-
catch {
32+
catch (error) {
33+
if (isLoaderError(error)) {
34+
throw error;
35+
}
3236
if (verbose === true) {
3337
console.info(`Failed to find .env file at path: ${filePath}`);
3438
}

dist/loaders/typescript.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export declare function checkIfTypescriptSupported(): void;

dist/loaders/typescript.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function checkIfTypescriptSupported() {
2+
if (!process.features.typescript) {
3+
const error = new Error('To load typescript files with env-cmd, you need to upgrade to node v23.6' +
4+
' or later. See https://nodejs.org/en/learn/typescript/run-natively');
5+
Object.assign(error, { code: 'ERR_UNKNOWN_FILE_EXTENSION' });
6+
throw error;
7+
}
8+
}

dist/parse-env-file.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from 'node:fs';
22
import { extname } from 'node:path';
33
import { pathToFileURL } from 'node:url';
44
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise } from './utils.js';
5+
import { checkIfTypescriptSupported } from './loaders/typescript.js';
56
/**
67
* Gets the environment vars from an env file
78
*/
@@ -16,6 +17,8 @@ export async function getEnvFileVars(envFilePath) {
1617
const ext = extname(absolutePath).toLowerCase();
1718
let env;
1819
if (IMPORT_HOOK_EXTENSIONS.includes(ext)) {
20+
if (/tsx?$/.test(ext))
21+
checkIfTypescriptSupported();
1922
// For some reason in ES Modules, only JSON file types need to be specifically delinated when importing them
2023
let attributeTypes = {};
2124
if (ext === '.json') {

dist/parse-rc-file.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { promisify } from 'node:util';
33
import { extname } from 'node:path';
44
import { pathToFileURL } from 'node:url';
55
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise } from './utils.js';
6+
import { checkIfTypescriptSupported } from './loaders/typescript.js';
67
const statAsync = promisify(stat);
78
const readFileAsync = promisify(readFile);
89
/**
@@ -23,6 +24,8 @@ export async function getRCFileVars({ environments, filePath }) {
2324
let parsedData = {};
2425
try {
2526
if (IMPORT_HOOK_EXTENSIONS.includes(ext)) {
27+
if (/tsx?$/.test(ext))
28+
checkIfTypescriptSupported();
2629
// For some reason in ES Modules, only JSON file types need to be specifically delinated when importing them
2730
let attributeTypes = {};
2831
if (ext === '.json') {

dist/utils.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ export declare function parseArgList(list: string): string[];
1111
* A simple function to test if the value is a promise/thenable
1212
*/
1313
export declare function isPromise<T>(value?: T | PromiseLike<T>): value is PromiseLike<T>;
14+
/** @returns true if the error is `ERR_UNKNOWN_FILE_EXTENSION` */
15+
export declare function isLoaderError(error: unknown): error is Error;

dist/utils.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@ import { resolve } from 'node:path';
22
import { homedir } from 'node:os';
33
import { cwd } from 'node:process';
44
// Special file extensions that node can natively import
5-
export const IMPORT_HOOK_EXTENSIONS = ['.json', '.js', '.cjs', '.mjs'];
5+
export const IMPORT_HOOK_EXTENSIONS = [
6+
'.json',
7+
'.js',
8+
'.cjs',
9+
'.mjs',
10+
'.ts',
11+
'.mts',
12+
'.cts',
13+
'.tsx',
14+
];
615
/**
716
* A simple function for resolving the path the user entered
817
*/
@@ -29,3 +38,9 @@ export function isPromise(value) {
2938
&& 'then' in value
3039
&& typeof value.then === 'function';
3140
}
41+
/** @returns true if the error is `ERR_UNKNOWN_FILE_EXTENSION` */
42+
export function isLoaderError(error) {
43+
return (error instanceof Error &&
44+
'code' in error &&
45+
error.code === 'ERR_UNKNOWN_FILE_EXTENSION');
46+
}

src/get-env-vars.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { GetEnvVarOptions, Environment } from './types.ts'
22
import { getRCFileVars } from './parse-rc-file.js'
33
import { getEnvFileVars } from './parse-env-file.js'
4+
import { isLoaderError } from './utils.js'
45

56
const RC_FILE_DEFAULT_LOCATIONS = ['./.env-cmdrc', './.env-cmdrc.js', './.env-cmdrc.json']
67
const ENV_FILE_DEFAULT_LOCATIONS = ['./.env', './.env.js', './.env.json']
@@ -34,7 +35,11 @@ export async function getEnvFile(
3435
}
3536
return env
3637
}
37-
catch {
38+
catch (error) {
39+
if (isLoaderError(error)) {
40+
throw error
41+
}
42+
3843
if (verbose === true) {
3944
console.info(`Failed to find .env file at path: ${filePath}`)
4045
}

src/loaders/typescript.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function checkIfTypescriptSupported() {
2+
if (!process.features.typescript) {
3+
const error = new Error(
4+
'To load typescript files with env-cmd, you need to upgrade to node v23.6' +
5+
' or later. See https://nodejs.org/en/learn/typescript/run-natively',
6+
);
7+
Object.assign(error, { code: 'ERR_UNKNOWN_FILE_EXTENSION' });
8+
throw error;
9+
}
10+
}

src/parse-env-file.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { extname } from 'node:path'
33
import { pathToFileURL } from 'node:url'
44
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise } from './utils.js'
55
import type { Environment } from './types.ts'
6+
import { checkIfTypescriptSupported } from './loaders/typescript.js'
67

78
/**
89
* Gets the environment vars from an env file
@@ -19,6 +20,8 @@ export async function getEnvFileVars(envFilePath: string): Promise<Environment>
1920
const ext = extname(absolutePath).toLowerCase()
2021
let env: unknown;
2122
if (IMPORT_HOOK_EXTENSIONS.includes(ext)) {
23+
if (/tsx?$/.test(ext)) checkIfTypescriptSupported();
24+
2225
// For some reason in ES Modules, only JSON file types need to be specifically delinated when importing them
2326
let attributeTypes = {}
2427
if (ext === '.json') {

0 commit comments

Comments
 (0)