From 42918d5e3b1a57ef4096b2ddeb67282075aa01ea Mon Sep 17 00:00:00 2001 From: Dmitry Ivakhnenko Date: Mon, 24 Aug 2020 17:24:27 +0300 Subject: [PATCH] feat: add basic support for esm (#914) * try load config as cjs and esm files * use new async function * fix tests * run tests in node, not in jsdom environment * Apply suggestions from code review Co-authored-by: Haroen Viaene * add interop default, for mjs config * fix lint error Co-authored-by: Haroen Viaene Co-authored-by: shipjs --- packages/shipjs-lib/babel.config.js | 2 +- packages/shipjs-lib/jest.config.js | 1 + .../lib/config/__tests__/cjs/ship.config.cjs | 3 ++ .../lib/config/__tests__/loadConfig.spec.js | 21 ++++++++----- .../shipjs-lib/src/lib/config/loadConfig.js | 30 ++++++++++++++++--- .../shipjs-lib/src/lib/util/getAppName.js | 8 ++--- packages/shipjs/babel.config.js | 8 ----- packages/shipjs/jest.config.js | 1 + packages/shipjs/src/flow/prepare.js | 4 +-- packages/shipjs/src/flow/release.js | 4 +-- .../shipjs/src/step/release/gatherRepoInfo.js | 6 ++-- 11 files changed, 56 insertions(+), 32 deletions(-) create mode 100644 packages/shipjs-lib/src/lib/config/__tests__/cjs/ship.config.cjs diff --git a/packages/shipjs-lib/babel.config.js b/packages/shipjs-lib/babel.config.js index a79d1195..c74fb53e 100644 --- a/packages/shipjs-lib/babel.config.js +++ b/packages/shipjs-lib/babel.config.js @@ -1,3 +1,3 @@ module.exports = { - presets: ['@babel/preset-env'], + presets: [['@babel/preset-env', { targets: { node: 'current' } }]], }; diff --git a/packages/shipjs-lib/jest.config.js b/packages/shipjs-lib/jest.config.js index 1e2d2f50..3bb760d7 100644 --- a/packages/shipjs-lib/jest.config.js +++ b/packages/shipjs-lib/jest.config.js @@ -2,6 +2,7 @@ module.exports = { transform: { '^.+\\.[t|j]sx?$': 'babel-jest', }, + testEnvironment: 'node', testPathIgnorePatterns: ['/src/lib/config/__tests__/example'], watchPathIgnorePatterns: ['/sandbox'], watchPlugins: [ diff --git a/packages/shipjs-lib/src/lib/config/__tests__/cjs/ship.config.cjs b/packages/shipjs-lib/src/lib/config/__tests__/cjs/ship.config.cjs new file mode 100644 index 00000000..bd0482ad --- /dev/null +++ b/packages/shipjs-lib/src/lib/config/__tests__/cjs/ship.config.cjs @@ -0,0 +1,3 @@ +module.exports = { + versionUpdated() {}, +}; diff --git a/packages/shipjs-lib/src/lib/config/__tests__/loadConfig.spec.js b/packages/shipjs-lib/src/lib/config/__tests__/loadConfig.spec.js index 22ba583e..484b9377 100644 --- a/packages/shipjs-lib/src/lib/config/__tests__/loadConfig.spec.js +++ b/packages/shipjs-lib/src/lib/config/__tests__/loadConfig.spec.js @@ -7,21 +7,26 @@ const baseConfig = expect.objectContaining({}); const d = (dirName) => path.resolve(__dirname, dirName); describe('loadConfig', () => { - it('does not throw when there is no config', () => { - expect(loadConfig(d('non-existing-dir'))).toMatchObject(baseConfig); + it('does not throw when there is no config', async () => { + expect(await loadConfig(d('non-existing-dir'))).toMatchObject(baseConfig); }); - it('should load config', () => { - expect(loadConfig(d('example'))).toMatchObject(baseConfig); + it('should load config', async () => { + expect(await loadConfig(d('example'))).toMatchObject(baseConfig); }); - it('should get function properly', () => { - const config = loadConfig(d('example')); + it('should load config with cjs ext', async () => { + const config = await loadConfig(d('cjs')); expect(typeof config.versionUpdated).toBe('function'); }); - it('should merge defaultConfig and userConfig', () => { - const config = loadConfig(d('example')); + it('should get function properly', async () => { + const config = await loadConfig(d('example')); + expect(typeof config.versionUpdated).toBe('function'); + }); + + it('should merge defaultConfig and userConfig', async () => { + const config = await loadConfig(d('example')); expect(config.conventionalChangelogArgs).toBe( defaultConfig.conventionalChangelogArgs ); diff --git a/packages/shipjs-lib/src/lib/config/loadConfig.js b/packages/shipjs-lib/src/lib/config/loadConfig.js index 2c7a16ba..9128cea4 100644 --- a/packages/shipjs-lib/src/lib/config/loadConfig.js +++ b/packages/shipjs-lib/src/lib/config/loadConfig.js @@ -1,13 +1,35 @@ import dotenv from 'dotenv'; import { resolve } from 'path'; -import { existsSync } from 'fs'; +import { promises as fs, constants } from 'fs'; import defaultConfig from './defaultConfig'; import mergeConfig from './mergeConfig'; dotenv.config(); -export default function loadConfig(dir = '.', filename = 'ship.config.js') { - const fullPath = resolve(dir, filename); - const userConfig = existsSync(fullPath) ? require(fullPath) : {}; +const exist = (path) => + fs + .access(path, constants.F_OK) + .then(() => path) + .catch(() => false); + +const pickDefault = (obj) => + typeof obj.default === 'object' ? obj.default : obj; + +export default async function loadConfig( + dir = '.', + filename = 'ship.config', + extensions = ['js', 'cjs', 'mjs'] +) { + const fullPaths = extensions.map((ext) => resolve(dir, `${filename}.${ext}`)); + + const fullPath = ( + await Promise.all(fullPaths.map((path) => exist(path))) + ).find((path) => path); + + const userConfig = + fullPath && (await exist(fullPath)) + ? await import(fullPath).then(pickDefault) + : {}; + return mergeConfig(defaultConfig, userConfig); } diff --git a/packages/shipjs-lib/src/lib/util/getAppName.js b/packages/shipjs-lib/src/lib/util/getAppName.js index 85abf94d..12b26cd3 100644 --- a/packages/shipjs-lib/src/lib/util/getAppName.js +++ b/packages/shipjs-lib/src/lib/util/getAppName.js @@ -1,12 +1,12 @@ -import { readFileSync } from 'fs'; +import { promises as fs } from 'fs'; import { resolve } from 'path'; import loadConfig from '../config/loadConfig'; -export default function getAppName(dir = '.') { - const { appName } = loadConfig(dir); +export default async function getAppName(dir = '.') { + const { appName } = await loadConfig(dir); if (appName) { return appName; } - const { name } = JSON.parse(readFileSync(resolve(dir, 'package.json'))); + const { name } = JSON.parse(await fs.readFile(resolve(dir, 'package.json'))); return name; } diff --git a/packages/shipjs/babel.config.js b/packages/shipjs/babel.config.js index 476ddcea..f037a1a2 100644 --- a/packages/shipjs/babel.config.js +++ b/packages/shipjs/babel.config.js @@ -9,12 +9,4 @@ module.exports = { }, ], ], - plugins: [ - [ - '@babel/plugin-transform-runtime', - { - regenerator: true, - }, - ], - ], }; diff --git a/packages/shipjs/jest.config.js b/packages/shipjs/jest.config.js index 904cc6ff..f3d7b53a 100644 --- a/packages/shipjs/jest.config.js +++ b/packages/shipjs/jest.config.js @@ -2,6 +2,7 @@ module.exports = { transform: { '^.+\\.[t|j]sx?$': 'babel-jest', }, + testEnvironment: 'node', watchPlugins: [ 'jest-watch-typeahead/filename', 'jest-watch-typeahead/testname', diff --git a/packages/shipjs/src/flow/prepare.js b/packages/shipjs/src/flow/prepare.js index e537a798..ca8c861b 100644 --- a/packages/shipjs/src/flow/prepare.js +++ b/packages/shipjs/src/flow/prepare.js @@ -45,7 +45,7 @@ async function prepare({ } printDeprecated({ firstRelease, releaseCount }); checkGitHubToken({ dryRun }); - const config = loadConfig(dir); + const config = await loadConfig(dir); const { currentVersion, baseBranch } = validate({ config, dir }); const { remote, forcePushBranches } = config; pull({ remote, currentBranch: baseBranch, dir, dryRun }); @@ -120,7 +120,7 @@ async function prepare({ dir, dryRun, }); - const appName = getAppName(dir); + const appName = await getAppName(dir); await notifyPrepared({ config, appName, diff --git a/packages/shipjs/src/flow/release.js b/packages/shipjs/src/flow/release.js index ba3b8a5e..2f69598d 100644 --- a/packages/shipjs/src/flow/release.js +++ b/packages/shipjs/src/flow/release.js @@ -26,7 +26,7 @@ async function release({ help = false, dir = '.', dryRun = false }) { printDryRunBanner(); } checkGitHubToken({ dryRun }); - const config = loadConfig(dir); + const config = await loadConfig(dir); const { remote } = config; const { currentVersion: version } = validate({ config, dir }); const { @@ -35,7 +35,7 @@ async function release({ help = false, dir = '.', dryRun = false }) { latestCommitUrl, repoURL, releaseTag, - } = gatherRepoInfo({ remote, version, dir }); + } = await gatherRepoInfo({ remote, version, dir }); const isYarn = detectYarn(dir); runTest({ isYarn, config, dir, dryRun }); runBuild({ isYarn, config, version, dir, dryRun }); diff --git a/packages/shipjs/src/step/release/gatherRepoInfo.js b/packages/shipjs/src/step/release/gatherRepoInfo.js index 76f476c8..b8411583 100644 --- a/packages/shipjs/src/step/release/gatherRepoInfo.js +++ b/packages/shipjs/src/step/release/gatherRepoInfo.js @@ -7,9 +7,9 @@ import { } from 'shipjs-lib'; import runStep from '../runStep'; -export default ({ remote, version, dir }) => - runStep({ title: 'Gathering repository information.' }, () => { - const appName = getAppName(dir); +export default async ({ remote, version, dir }) => + await runStep({ title: 'Gathering repository information.' }, async () => { + const appName = await getAppName(dir); const latestCommitHash = getLatestCommitHash(dir); const latestCommitUrl = getCommitUrl(remote, latestCommitHash, dir); const { url: repoURL } = getRepoInfo(remote, dir);