Merge pull request #395 from toddbluhm/kh/crash

fix(*): fix crash on node v18.0 caused by Import Attribute syntax
This commit is contained in:
Kyℓe Hensel 2024-12-11 18:37:06 +11:00 committed by GitHub
commit e1e0001965
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 36 additions and 10 deletions

5
dist/parse-args.js vendored
View File

@ -1,6 +1,9 @@
import { createRequire } from 'node:module';
import { Command } from '@commander-js/extra-typings';
import { parseArgList } from './utils.js';
import { default as packageJson } from '../package.json' with { type: 'json' };
// TODO: once we drop support for node <v20.10, this can be converted to
// a normal import statement
const packageJson = createRequire(import.meta.url)('../package.json');
/**
* Parses the arguments passed into the cli
*/

View File

@ -1,7 +1,7 @@
import { existsSync, readFileSync } from 'node:fs';
import { extname } from 'node:path';
import { pathToFileURL } from 'node:url';
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise } from './utils.js';
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise, importAttributesKeyword } from './utils.js';
/**
* Gets the environment vars from an env file
*/
@ -19,7 +19,7 @@ export async function getEnvFileVars(envFilePath) {
// For some reason in ES Modules, only JSON file types need to be specifically delinated when importing them
let attributeTypes = {};
if (ext === '.json') {
attributeTypes = { with: { type: 'json' } };
attributeTypes = { [importAttributesKeyword]: { type: 'json' } };
}
const res = await import(pathToFileURL(absolutePath).href, attributeTypes);
if ('default' in res) {

View File

@ -2,7 +2,7 @@ import { stat, readFile } from 'node:fs';
import { promisify } from 'node:util';
import { extname } from 'node:path';
import { pathToFileURL } from 'node:url';
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise } from './utils.js';
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise, importAttributesKeyword } from './utils.js';
const statAsync = promisify(stat);
const readFileAsync = promisify(readFile);
/**
@ -26,7 +26,7 @@ export async function getRCFileVars({ environments, filePath }) {
// For some reason in ES Modules, only JSON file types need to be specifically delinated when importing them
let attributeTypes = {};
if (ext === '.json') {
attributeTypes = { with: { type: 'json' } };
attributeTypes = { [importAttributesKeyword]: { type: 'json' } };
}
const res = await import(pathToFileURL(absolutePath).href, attributeTypes);
if ('default' in res) {

1
dist/utils.d.ts vendored
View File

@ -11,3 +11,4 @@ export declare function parseArgList(list: string): string[];
* A simple function to test if the value is a promise/thenable
*/
export declare function isPromise<T>(value?: T | PromiseLike<T>): value is PromiseLike<T>;
export declare const importAttributesKeyword: string;

6
dist/utils.js vendored
View File

@ -29,3 +29,9 @@ export function isPromise(value) {
&& 'then' in value
&& typeof value.then === 'function';
}
// "Import Attributes" are only supported since node v18.20 and v20.10.
// For older node versions, we have to use "Import Assertions".
// TODO: remove this check when we drop support for node v20
const [major, minor] = process.version.slice(1).split('.').map(Number);
const legacyImportAssertions = (major === 18 && minor < 20) || (major === 20 && minor < 10);
export const importAttributesKeyword = legacyImportAssertions ? 'assert' : 'with';

View File

@ -1,7 +1,13 @@
import { createRequire } from 'node:module'
import { Command } from '@commander-js/extra-typings'
import type { EnvCmdOptions, CommanderOptions, EnvFileOptions, RCFileOptions } from './types.ts'
import { parseArgList } from './utils.js'
import { default as packageJson } from '../package.json' with { type: 'json' };
// TODO: once we drop support for node <v20.10, this can be converted to
// a normal import statement
const packageJson = createRequire(import.meta.url)('../package.json') as {
version: string;
}
/**
* Parses the arguments passed into the cli

View File

@ -1,7 +1,7 @@
import { existsSync, readFileSync } from 'node:fs'
import { extname } from 'node:path'
import { pathToFileURL } from 'node:url'
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise } from './utils.js'
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise, importAttributesKeyword } from './utils.js'
import type { Environment } from './types.ts'
/**
@ -22,7 +22,7 @@ export async function getEnvFileVars(envFilePath: string): Promise<Environment>
// For some reason in ES Modules, only JSON file types need to be specifically delinated when importing them
let attributeTypes = {}
if (ext === '.json') {
attributeTypes = { with: { type: 'json' } }
attributeTypes = { [importAttributesKeyword]: { type: 'json' } }
}
const res = await import(pathToFileURL(absolutePath).href, attributeTypes) as Environment | { default: Environment }
if ('default' in res) {

View File

@ -2,7 +2,7 @@ import { stat, readFile } from 'node:fs'
import { promisify } from 'node:util'
import { extname } from 'node:path'
import { pathToFileURL } from 'node:url'
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise } from './utils.js'
import { resolveEnvFilePath, IMPORT_HOOK_EXTENSIONS, isPromise, importAttributesKeyword } from './utils.js'
import type { Environment, RCEnvironment } from './types.ts'
const statAsync = promisify(stat)
@ -33,7 +33,7 @@ export async function getRCFileVars(
// For some reason in ES Modules, only JSON file types need to be specifically delinated when importing them
let attributeTypes = {}
if (ext === '.json') {
attributeTypes = { with: { type: 'json' } }
attributeTypes = { [importAttributesKeyword]: { type: 'json' } }
}
const res = await import(pathToFileURL(absolutePath).href, attributeTypes) as RCEnvironment | { default: RCEnvironment }
if ('default' in res) {

View File

@ -32,3 +32,13 @@ export function isPromise<T>(value?: T | PromiseLike<T>): value is PromiseLike<T
&& 'then' in value
&& typeof value.then === 'function'
}
// "Import Attributes" are only supported since node v18.20 and v20.10.
// For older node versions, we have to use "Import Assertions".
// TODO: remove this check when we drop support for node v20
const [major, minor] = process.version.slice(1).split('.').map(Number)
const legacyImportAssertions =
(major === 18 && minor < 20) || (major === 20 && minor < 10)
export const importAttributesKeyword = legacyImportAssertions ? 'assert' : 'with'