Skip to content

Commit

Permalink
feat!: convert to ESM (#318)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the codebase has migrated to native ESM which requires node 12+ and may cause issues downstream
  • Loading branch information
jquense committed Sep 17, 2021
1 parent d38e190 commit 5862163
Show file tree
Hide file tree
Showing 72 changed files with 1,503 additions and 1,134 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = {
'no-console': 'off',
'import/no-dynamic-require': 'off',
'prettier/prettier': 'error',
'import/extensions': ['error', 'ignorePackages'],
},
overrides: [
{
Expand Down
6 changes: 5 additions & 1 deletion packages/build/cli.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#!/usr/bin/env node

require('@4c/cli-core/createCliFromCommand')(require('./command'));
import createCliFromCommand from '@4c/cli-core/createCliFromCommand';

import * as Command from './command.js';

createCliFromCommand(Command);
149 changes: 78 additions & 71 deletions packages/build/command.js
Original file line number Diff line number Diff line change
@@ -1,79 +1,86 @@
const path = require('path');
const { debuglog } = require('util');
import { createRequire } from 'module';
import { dirname, isAbsolute, join, resolve } from 'path';
import { debuglog } from 'util';

const { chalk, symbols, info } = require('@4c/cli-core/ConsoleUtilities');
const { getPackages } = require('@manypkg/get-packages');
const execa = require('execa');
const fs = require('fs-extra');
const Listr = require('listr');
import { chalk, info, symbols } from '@4c/cli-core/ConsoleUtilities';
import { getPackages } from '@manypkg/get-packages';
import execa from 'execa';
import fsExtra from 'fs-extra';
import Listr from 'listr';

const { copy, copyRest } = require('./copy');
import { copy, copyRest } from './copy.js';

const require = createRequire(import.meta.url);

const debug = debuglog('@4c/build');
const { existsSync, readJson, readJsonSync } = fsExtra;

function getCli(pkg, cmd) {
const pkgPath = require.resolve(`${pkg}/package.json`);
const { bin } = fs.readJsonSync(pkgPath);
const loc = path.join(path.dirname(pkgPath), bin[cmd]);
const { bin } = readJsonSync(pkgPath);
const loc = join(dirname(pkgPath), bin[cmd]);

return loc;
}

exports.command = '$0 [patterns..]';
export const command = '$0 [patterns..]';

exports.describe =
export const describe =
'Compiles code via babel as well as Typescript type def files when appropriate.\n\n' +
'Boolean flags can be negated by prefixing with --no-* (--foo, --no-foo)';

exports.builder = (_) =>
_.positional('patterns', { default: ['src'] })
.option('out-dir', {
alias: 'd',
type: 'string',
})
.option('type-dir', {
type: 'string',
describe:
'The location of any additional type defs, to be copied to the output folders',
})
.option('esm', {
type: 'boolean',
default: undefined,
describe: 'Builds an esm build',
})
.option('extensions', {
alias: 'x',
default: ['.js', '.ts', '.tsx'],
describe: 'The extensions of files to compile',
})
.option('clean', {
type: 'boolean',
default: true,
describe: 'Remove out directory before building',
})
.option('tsconfig', {
type: 'path',
describe: 'The tsconfig.json location to use for type defs',
})
.option('only-types', {
type: 'boolean',
describe: 'Compile only the type definitions',
})
// off with `no-types`
.option('types', {
type: 'boolean',
default: true,
describe: 'Compile type defs',
})
.option('copy-files', {
type: 'boolean',
default: true,
describe: 'When compiling a directory copy over non-compilable files',
})
// so we can pass anything after -- to babel
.parserConfiguration({
'populate--': true,
});
export function builder(_) {
return (
_.positional('patterns', { default: ['src'] })
.option('out-dir', {
alias: 'd',
type: 'string',
})
.option('type-dir', {
type: 'string',
describe:
'The location of any additional type defs, to be copied to the output folders',
})
.option('esm', {
type: 'boolean',
default: undefined,
describe: 'Builds an esm build',
})
.option('extensions', {
alias: 'x',
default: ['.js', '.ts', '.tsx'],
describe: 'The extensions of files to compile',
})
.option('clean', {
type: 'boolean',
default: true,
describe: 'Remove out directory before building',
})
.option('tsconfig', {
type: 'path',
describe: 'The tsconfig.json location to use for type defs',
})
.option('only-types', {
type: 'boolean',
describe: 'Compile only the type definitions',
})
// off with `no-types`
.option('types', {
type: 'boolean',
default: true,
describe: 'Compile type defs',
})
.option('copy-files', {
type: 'boolean',
default: true,
describe: 'When compiling a directory copy over non-compilable files',
})
// so we can pass anything after -- to babel
.parserConfiguration({
'populate--': true,
})
);
}

function run(...args) {
return execa(...args, {
Expand All @@ -90,18 +97,18 @@ function run(...args) {
let babelCmd;

const safeToDelete = (dir, cwd = process.cwd()) => {
const resolvedDir = path.isAbsolute(dir) ? dir : path.resolve(cwd, dir);
const resolvedDir = isAbsolute(dir) ? dir : resolve(cwd, dir);

return resolvedDir.startsWith(cwd) && resolvedDir !== cwd;
};

const getTsconfig = () => {
if (fs.existsSync('./tsconfig.build.json')) return './tsconfig.build.json';
if (fs.existsSync('./tsconfig.json')) return './tsconfig.json';
if (existsSync('./tsconfig.build.json')) return './tsconfig.build.json';
if (existsSync('./tsconfig.json')) return './tsconfig.json';
return null;
};

exports.handler = async ({
export async function handler({
patterns,
esm,
outDir,
Expand All @@ -113,14 +120,14 @@ exports.handler = async ({
copyFiles,
'--': passthrough,
...options
}) => {
}) {
const { tool } = await getPackages();
const monorepo = tool !== 'root';

const pkg = await fs.readJson('package.json');
const pkg = await readJson('package.json');
const tsconfig = types && (options.tsconfig || getTsconfig());

const buildTypes = tsconfig && !!fs.existsSync(tsconfig);
const buildTypes = tsconfig && !!existsSync(tsconfig);
const tscCmd = buildTypes && getCli('typescript', 'tsc');

if (tsconfig && !options.tsconfig) {
Expand All @@ -130,15 +137,15 @@ exports.handler = async ({
}
if (!outDir) {
// eslint-disable-next-line no-param-reassign
outDir = pkg.main && path.dirname(pkg.main);
outDir = pkg.main && dirname(pkg.main);
}

const isSameEntry = pkg.module && pkg.main && pkg.module === pkg.main;

let esmRoot;
let esmRootInOutDir = false;
if (esm !== false) {
esmRoot = pkg.module && path.dirname(pkg.module);
esmRoot = pkg.module && dirname(pkg.module);

if (esm === true && !esmRoot) {
throw new Error(
Expand Down Expand Up @@ -267,4 +274,4 @@ exports.handler = async ({
console.error(err.message);
process.exitCode = 1;
}
};
}
14 changes: 7 additions & 7 deletions packages/build/copy.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
const path = require('path');
import { relative, resolve } from 'path';

const cpy = require('cpy');
const fs = require('fs-extra');
import cpy from 'cpy';
import fsExtra from 'fs-extra';

const relativeOut = (src, outDir) =>
path.relative(path.resolve(src), path.resolve(outDir));
const relativeOut = (src, outDir) => relative(resolve(src), resolve(outDir));

function copy(patterns, base, outDir) {
return cpy(
Expand All @@ -22,7 +21,8 @@ function copyRest(sources, outDir, extensions) {
return Promise.all(
sources.map((base) => {
// babel allows this, tho we don't usually specify file names in
if (!fs.statSync(base).isDirectory()) {

if (!fsExtra.statSync(base).isDirectory()) {
return cpy([base, '!**/__tests__/**', '!**/__mocks__/**'], outDir);
}

Expand All @@ -40,4 +40,4 @@ function copyRest(sources, outDir, extensions) {
);
}

module.exports = { copy, copyRest };
export { copy, copyRest };
18 changes: 12 additions & 6 deletions packages/build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
"bugs": {
"url": "https://github.com/4Catalyzer/cli/issues"
},
"type": "module",
"license": "MIT",
"author": "4Catalyzer",
"main": "command.js",
"exports": {
".": "./command.js",
"./command": "./command.js",
"./copy": "./copy.js"
},
"bin": {
"build": "cli.js"
},
Expand All @@ -22,14 +28,14 @@
},
"dependencies": {
"@4c/cli-core": "^2.3.0",
"@babel/cli": "^7.12.13",
"@babel/core": "^7.12.13",
"@babel/cli": "^7.15.4",
"@babel/core": "^7.15.5",
"@manypkg/get-packages": "^1.1.1",
"cpy": "^8.1.1",
"execa": "^5.0.0",
"fs-extra": "^9.1.0",
"cpy": "^8.1.2",
"execa": "^5.1.1",
"fs-extra": "^10.0.0",
"listr": "^0.14.3",
"typescript": "^4.1.3"
"typescript": "^4.4.3"
},
"publishConfig": {
"access": "public"
Expand Down
8 changes: 4 additions & 4 deletions packages/cli-core/ArgUtilities.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const globby = require('globby');
import { globby } from 'globby';

exports.resolveFilePatterns = (
export function resolveFilePatterns(
patterns,
{ ignoreNodeModules = true, ...rest } = {},
) => {
) {
let fullPatterns = patterns;

if (ignoreNodeModules)
Expand All @@ -18,4 +18,4 @@ exports.resolveFilePatterns = (
]);

return globby(fullPatterns, { dot: true, nodir: true, ...rest });
};
}

0 comments on commit 5862163

Please sign in to comment.