From 3e21d396736312ade01ab66b7333aab6b8fecd6c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 30 Mar 2024 12:25:09 +0100 Subject: [PATCH 1/3] feat(esm): support new import attributes syntax --- src/esm.ts | 66 ++++++++++++++++++++++++++++------------------ src/types.ts | 6 +---- test/index.test.ts | 9 +++++++ 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/esm.ts b/src/esm.ts index 4199e54..0b87553 100644 --- a/src/esm.ts +++ b/src/esm.ts @@ -2,13 +2,20 @@ import { CodegenOptions } from "./types"; import { genString } from "./string"; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import -// https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#sec-imports export type ESMImport = string | { name: string; as?: string }; +export interface ESMCodeGenOptions extends CodegenOptions { + // https://github.com/tc39/proposal-import-attributes + // https://nodejs.org/api/esm.html#import-attributes + attributes?: { type: string; }; + /** @deprecated use attributes */ + assert?: { type: string; }; +} + export function genImport( specifier: string, imports?: ESMImport | ESMImport[], - options: CodegenOptions = {}, + options: ESMCodeGenOptions = {}, ) { return _genStatement("import", specifier, imports, options); } @@ -16,7 +23,7 @@ export function genImport( export function genTypeImport( specifier: string, imports: ESMImport[], - options: CodegenOptions = {}, + options: ESMCodeGenOptions = {}, ) { return _genStatement("import type", specifier, imports, options); } @@ -24,7 +31,7 @@ export function genTypeImport( export function genTypeExport( specifier: string, imports: ESMImport[], - options: CodegenOptions = {}, + options: ESMCodeGenOptions = {}, ) { return _genStatement("export type", specifier, imports, options); } @@ -32,7 +39,7 @@ export function genTypeExport( export const genInlineTypeImport = ( specifier: string, name = "default", - options: CodegenOptions = {}, + options: ESMCodeGenOptions = {}, ) => { return `typeof ${genDynamicImport(specifier, { ...options, @@ -47,7 +54,7 @@ export type ESMExport = string | { name: string; as?: string }; export function genExport( specifier: string, exports?: ESMExport | ESMExport[], - options: CodegenOptions = {}, + options: ESMCodeGenOptions = {}, ) { return _genStatement("export", specifier, exports, options); } @@ -58,7 +65,7 @@ function _genStatement( type: ImportExportType, specifier: string, names?: ESMImportOrExport | ESMImportOrExport[], - options: CodegenOptions = {}, + options: ESMCodeGenOptions = {}, ) { const specifierString = genString(specifier, options); if (!names) { @@ -86,35 +93,36 @@ function _genStatement( return `${type} { ${namesString} } from ${genString( specifier, options, - )}${_genAssertClause(type, options.assert)};`; + )}${_genImportAttributes(type, options)};`; } return `${type} ${namesString} from ${genString( specifier, options, - )}${_genAssertClause(type, options.assert)};`; + )}${_genImportAttributes(type, options)};`; } -function _genAssertClause(type: ImportExportType, assert?: { type: string }) { +function _genImportAttributes(type: ImportExportType, options: ESMCodeGenOptions) { // import assertions isn't specified type-only import or export on Typescript if (type === "import type" || type === "export type") { return ""; } - // currently, `type` only - if (!assert || typeof assert !== "object") { - return ""; + + if (typeof options.attributes?.type === 'string') { + return ` with { type: ${genString(options.attributes.type)} }`; + } + + // TODO: Remove deprecated `assert` in the next major release + if (typeof options.assert?.type === 'string') { + return ` assert { type: ${genString(options.assert.type)} }`; } - return ` assert { type: ${genString(assert.type)} }`; + + return ""; } -export interface DynamicImportOptions extends CodegenOptions { +export interface DynamicImportOptions extends ESMCodeGenOptions { comment?: string; wrapper?: boolean; interopDefault?: boolean; - // https://github.com/tc39/proposal-import-assertions - // https://tc39.es/proposal-import-assertions/ - assert?: { - type: string; - }; } export function genDynamicImport( specifier: string, @@ -125,18 +133,24 @@ export function genDynamicImport( const ineropString = options.interopDefault ? ".then(m => m.default || m)" : ""; - const optionsString = _genDynamicImportOptions(options); + const optionsString = _genDynamicImportAttributes(options); return `${wrapperString}import(${genString( specifier, options, )}${commentString}${optionsString})${ineropString}`; } -function _genDynamicImportOptions(options: DynamicImportOptions = {}) { - // currently, `assert` option only - return options.assert && typeof options.assert === "object" - ? `, { assert: { type: ${genString(options.assert.type)} } }` - : ""; +function _genDynamicImportAttributes(options: DynamicImportOptions = {}) { + // TODO: Remove deprecated `assert` in the next major release + if (typeof options.assert?.type === 'string') { + return `, { assert: { type: ${genString(options.assert.type)} } }`; + } + + if (typeof options.attributes?.type === 'string') { + return `, { with: { type: ${genString(options.attributes.type)} } }`; + } + + return ""; } export function genSafeVariableName(name: string) { diff --git a/src/types.ts b/src/types.ts index bdfcf5b..8fb6313 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,4 @@ export interface CodegenOptions { singleQuotes?: boolean; - // https://github.com/tc39/proposal-import-assertions - // https://tc39.es/proposal-import-assertions/ - assert?: { - type: string; - }; + } diff --git a/test/index.test.ts b/test/index.test.ts index bba8911..df5e873 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -36,6 +36,11 @@ const genImportTests = [ code: 'import { foo } from "pkg" assert { type: "json" };', options: { assert: { type: "json" } }, }, + { + names: ["foo"], + code: 'import { foo } from "pkg" with { type: "json" };', + options: { attributes: { type: "json" } }, + }, ]; describe("genImport", () => { @@ -87,6 +92,10 @@ const genDynamicImportTests = [ opts: { assert: { type: "json" } }, code: '() => import("pkg", { assert: { type: "json" } })', }, + { + opts: { attributes: { type: "json" } }, + code: '() => import("pkg", { with: { type: "json" } })', + }, ]; describe("genDynamicImport", () => { From 3c68b7bfb7fbe83288e60f500edf790139e44f94 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sat, 30 Mar 2024 11:29:02 +0000 Subject: [PATCH 2/3] chore: apply automated updates --- src/esm.ts | 17 ++++++++++------- src/types.ts | 1 - 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/esm.ts b/src/esm.ts index 0b87553..a1a2b20 100644 --- a/src/esm.ts +++ b/src/esm.ts @@ -7,9 +7,9 @@ export type ESMImport = string | { name: string; as?: string }; export interface ESMCodeGenOptions extends CodegenOptions { // https://github.com/tc39/proposal-import-attributes // https://nodejs.org/api/esm.html#import-attributes - attributes?: { type: string; }; + attributes?: { type: string }; /** @deprecated use attributes */ - assert?: { type: string; }; + assert?: { type: string }; } export function genImport( @@ -101,18 +101,21 @@ function _genStatement( )}${_genImportAttributes(type, options)};`; } -function _genImportAttributes(type: ImportExportType, options: ESMCodeGenOptions) { +function _genImportAttributes( + type: ImportExportType, + options: ESMCodeGenOptions, +) { // import assertions isn't specified type-only import or export on Typescript if (type === "import type" || type === "export type") { return ""; } - if (typeof options.attributes?.type === 'string') { + if (typeof options.attributes?.type === "string") { return ` with { type: ${genString(options.attributes.type)} }`; } // TODO: Remove deprecated `assert` in the next major release - if (typeof options.assert?.type === 'string') { + if (typeof options.assert?.type === "string") { return ` assert { type: ${genString(options.assert.type)} }`; } @@ -142,11 +145,11 @@ export function genDynamicImport( function _genDynamicImportAttributes(options: DynamicImportOptions = {}) { // TODO: Remove deprecated `assert` in the next major release - if (typeof options.assert?.type === 'string') { + if (typeof options.assert?.type === "string") { return `, { assert: { type: ${genString(options.assert.type)} } }`; } - if (typeof options.attributes?.type === 'string') { + if (typeof options.attributes?.type === "string") { return `, { with: { type: ${genString(options.attributes.type)} } }`; } diff --git a/src/types.ts b/src/types.ts index 8fb6313..588ac39 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,3 @@ export interface CodegenOptions { singleQuotes?: boolean; - } From 5710f895164be7b6fc219f371b8fcf42ae047819 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 30 Mar 2024 12:29:34 +0100 Subject: [PATCH 3/3] refactor type to top --- src/esm.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/esm.ts b/src/esm.ts index a1a2b20..bfb5f37 100644 --- a/src/esm.ts +++ b/src/esm.ts @@ -12,6 +12,12 @@ export interface ESMCodeGenOptions extends CodegenOptions { assert?: { type: string }; } +export interface DynamicImportOptions extends ESMCodeGenOptions { + comment?: string; + wrapper?: boolean; + interopDefault?: boolean; +} + export function genImport( specifier: string, imports?: ESMImport | ESMImport[], @@ -122,11 +128,6 @@ function _genImportAttributes( return ""; } -export interface DynamicImportOptions extends ESMCodeGenOptions { - comment?: string; - wrapper?: boolean; - interopDefault?: boolean; -} export function genDynamicImport( specifier: string, options: DynamicImportOptions = {},