From db93f8942d5c0ed3af80223b1106fddf2b2f0e47 Mon Sep 17 00:00:00 2001 From: guillaumervls <3765057+guillaumervls@users.noreply.github.com> Date: Wed, 15 Sep 2021 15:38:29 +0200 Subject: [PATCH 1/4] Add support for .gmrc as an ES Module --- src/commands/_common.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/commands/_common.ts b/src/commands/_common.ts index 971c2dd..f6294cc 100644 --- a/src/commands/_common.ts +++ b/src/commands/_common.ts @@ -63,14 +63,18 @@ interface Options { */ export async function getSettings(options: Options = {}): Promise { const { configFile } = options; - const tryRequire = (path: string): Settings => { + const tryRequire = async (path: string): Promise => { // If the file is e.g. `foo.js` then Node `require('foo.js')` would look in // `node_modules`; we don't want this - instead force it to be a relative // path. const relativePath = resolve(process.cwd(), path); try { - return require(relativePath); + try { + return (await import(relativePath)).default; + } catch (e) { + return require(relativePath); + } } catch (e) { throw new Error( `Failed to import '${relativePath}'; error:\n ${e.stack.replace( From d58af15bfd05cf85b2cb1468a7fb6c879e197110 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 23 Sep 2021 12:07:19 +0100 Subject: [PATCH 2/4] Just use import, no require --- src/commands/_common.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/commands/_common.ts b/src/commands/_common.ts index f6294cc..e4c0bef 100644 --- a/src/commands/_common.ts +++ b/src/commands/_common.ts @@ -63,18 +63,14 @@ interface Options { */ export async function getSettings(options: Options = {}): Promise { const { configFile } = options; - const tryRequire = async (path: string): Promise => { + const tryImport = async (path: string): Promise => { // If the file is e.g. `foo.js` then Node `require('foo.js')` would look in // `node_modules`; we don't want this - instead force it to be a relative // path. const relativePath = resolve(process.cwd(), path); try { - try { - return (await import(relativePath)).default; - } catch (e) { - return require(relativePath); - } + return (await import(relativePath)).default; } catch (e) { throw new Error( `Failed to import '${relativePath}'; error:\n ${e.stack.replace( @@ -90,15 +86,15 @@ export async function getSettings(options: Options = {}): Promise { throw new Error(`Failed to import '${configFile}': file not found`); } - if (configFile.endsWith(".js")) { - return tryRequire(configFile); + if (configFile.endsWith(".js") || configFile.endsWith(".mjs") || configFile.endsWith(".cjs")) { + return tryImport(configFile); } else { return await getSettingsFromJSON(configFile); } } else if (await exists(DEFAULT_GMRC_PATH)) { return await getSettingsFromJSON(DEFAULT_GMRC_PATH); } else if (await exists(DEFAULT_GMRCJS_PATH)) { - return tryRequire(DEFAULT_GMRCJS_PATH); + return tryImport(DEFAULT_GMRCJS_PATH); } else { throw new Error( "No .gmrc file found; please run `graphile-migrate init` first.", From bec92b73d4b2a759ea8534f0d0121c90d6cc95f9 Mon Sep 17 00:00:00 2001 From: guillaumervls <3765057+guillaumervls@users.noreply.github.com> Date: Thu, 23 Sep 2021 18:32:37 +0200 Subject: [PATCH 3/4] Run prettier --- src/commands/_common.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/commands/_common.ts b/src/commands/_common.ts index e4c0bef..8a57708 100644 --- a/src/commands/_common.ts +++ b/src/commands/_common.ts @@ -86,7 +86,11 @@ export async function getSettings(options: Options = {}): Promise { throw new Error(`Failed to import '${configFile}': file not found`); } - if (configFile.endsWith(".js") || configFile.endsWith(".mjs") || configFile.endsWith(".cjs")) { + if ( + configFile.endsWith(".js") || + configFile.endsWith(".mjs") || + configFile.endsWith(".cjs") + ) { return tryImport(configFile); } else { return await getSettingsFromJSON(configFile); From baad448df4d0bcde4d1b3912c04845cffcf6fd99 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 14 Jul 2022 11:13:49 +0100 Subject: [PATCH 4/4] Add CJS/MJS hinting, and handle 'require' error to retry as ESM --- src/commands/_common.ts | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/commands/_common.ts b/src/commands/_common.ts index 8a57708..4e111f5 100644 --- a/src/commands/_common.ts +++ b/src/commands/_common.ts @@ -63,14 +63,36 @@ interface Options { */ export async function getSettings(options: Options = {}): Promise { const { configFile } = options; - const tryImport = async (path: string): Promise => { + const tryImport = async ( + path: string, + mode: "cjs" | "mjs" | "js", + ): Promise => { // If the file is e.g. `foo.js` then Node `require('foo.js')` would look in // `node_modules`; we don't want this - instead force it to be a relative // path. const relativePath = resolve(process.cwd(), path); try { - return (await import(relativePath)).default; + if (mode === "cjs") { + return require(relativePath); + } else if (mode === "mjs") { + return (await import(relativePath)).default; + } else { + // try and require(CJS); but on ESM error, retry with import + try { + return require(relativePath); + } catch (e) { + if ( + e.code === "ERR_REQUIRE_ESM" || + (e.constructor.name === "SyntaxError" && + e.message.includes(" token 'export'")) + ) { + return tryImport(relativePath, "mjs"); + } else { + throw e; + } + } + } } catch (e) { throw new Error( `Failed to import '${relativePath}'; error:\n ${e.stack.replace( @@ -86,19 +108,19 @@ export async function getSettings(options: Options = {}): Promise { throw new Error(`Failed to import '${configFile}': file not found`); } - if ( - configFile.endsWith(".js") || - configFile.endsWith(".mjs") || - configFile.endsWith(".cjs") - ) { - return tryImport(configFile); + if (configFile.endsWith(".js")) { + return tryImport(configFile, "js"); + } else if (configFile.endsWith(".mjs")) { + return tryImport(configFile, "mjs"); + } else if (configFile.endsWith(".cjs")) { + return tryImport(configFile, "cjs"); } else { return await getSettingsFromJSON(configFile); } } else if (await exists(DEFAULT_GMRC_PATH)) { return await getSettingsFromJSON(DEFAULT_GMRC_PATH); } else if (await exists(DEFAULT_GMRCJS_PATH)) { - return tryImport(DEFAULT_GMRCJS_PATH); + return tryImport(DEFAULT_GMRCJS_PATH, "js"); } else { throw new Error( "No .gmrc file found; please run `graphile-migrate init` first.",