refactor: cli
This commit is contained in:
parent
78dc275d85
commit
21605c3e2c
|
@ -1,5 +1,4 @@
|
|||
'@flecks/build':
|
||||
packageManager: yarn
|
||||
'@flecks/build': {}
|
||||
'@flecks/core:./packages/core': {}
|
||||
'@flecks/create:./packages/create-app': {}
|
||||
'@flecks/create:./packages/create-fleck': {}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
const {readFile, writeFile} = require('fs/promises');
|
||||
const {
|
||||
join,
|
||||
sep,
|
||||
} = require('path');
|
||||
const {join} = require('path');
|
||||
|
||||
const {dump: dumpYml, load: loadYml} = require('js-yaml');
|
||||
|
||||
|
@ -10,10 +7,9 @@ const {
|
|||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
} = process.env;
|
||||
|
||||
module.exports = async (fleck, path) => {
|
||||
const key = [fleck].concat(path ? `.${sep}${join('packages', path)}` : []).join(':');
|
||||
module.exports = async (paths) => {
|
||||
const ymlPath = join(FLECKS_CORE_ROOT, 'build', 'flecks.yml');
|
||||
let yml = loadYml(await readFile(ymlPath));
|
||||
yml = Object.fromEntries(Object.entries(yml).concat([[key, {}]]));
|
||||
yml = Object.fromEntries(Object.entries(yml).concat(paths.map((path) => [path, {}])));
|
||||
await writeFile(ymlPath, dumpYml(yml, {sortKeys: true}));
|
||||
};
|
|
@ -17,12 +17,15 @@ const {
|
|||
stringLiteral,
|
||||
} = require('@babel/types');
|
||||
const D = require('@flecks/core/build/debug');
|
||||
const {processCode, spawnWith} = require('@flecks/core/server');
|
||||
const {Argument, Option, program} = require('commander');
|
||||
const {
|
||||
add,
|
||||
lockFile,
|
||||
spawnWith,
|
||||
} = require('@flecks/core/server');
|
||||
const {glob} = require('glob');
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
const addFleckToYml = require('./add-fleck-to-yml');
|
||||
const addPathsToYml = require('./add-paths-to-yml');
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
|
@ -55,26 +58,23 @@ function stringLiteralSinglequote(value) {
|
|||
}
|
||||
|
||||
exports.commands = (program, flecks) => {
|
||||
const {packageManager} = flecks.get('@flecks/build');
|
||||
const commands = {
|
||||
add: {
|
||||
args: [
|
||||
new Argument('<fleck>', 'fleck'),
|
||||
program.createArgument('<packages...>', 'packages to add'),
|
||||
],
|
||||
options: [
|
||||
program.createOption('-d, --dev-dependency', 'add to dev dependencies'),
|
||||
program.createOption('-pm,--package-manager <binary>', 'package manager binary')
|
||||
.choices(['npm', 'bun', 'pnpm', 'yarn']),
|
||||
],
|
||||
description: 'Add a fleck to your application.',
|
||||
action: async (fleck, {devDependency}) => {
|
||||
const args = [];
|
||||
if (['bun', 'yarn'].includes(packageManager)) {
|
||||
args.push(packageManager, ['add', ...(devDependency ? ['--dev'] : []), fleck]);
|
||||
}
|
||||
else {
|
||||
args.push(packageManager, ['install', ...(devDependency ? ['--save-dev'] : []), fleck]);
|
||||
}
|
||||
args.push({stdio: 'inherit'});
|
||||
await processCode(spawn(...args));
|
||||
description: 'Add flecks to your application.',
|
||||
action: async (packages, {devDependency, packageManager}) => {
|
||||
await add({
|
||||
dev: devDependency,
|
||||
packageManager,
|
||||
packages,
|
||||
});
|
||||
// If it seems like we're in a fleck path, update the bootstrap dependencies if possible.
|
||||
const bootstrapPath = join(FLECKS_CORE_ROOT, 'build', 'flecks.bootstrap.js');
|
||||
let code;
|
||||
|
@ -107,7 +107,7 @@ exports.commands = (program, flecks) => {
|
|||
const seen = {};
|
||||
// Add the fleck to dependencies.
|
||||
dependencies.elements = elements
|
||||
.concat(stringLiteralSinglequote(fleck))
|
||||
.concat(packages.map((fleck) => stringLiteralSinglequote(fleck)))
|
||||
// Filter duplicate literal strings.
|
||||
.filter((node) => {
|
||||
if (isStringLiteral(node)) {
|
||||
|
@ -129,35 +129,29 @@ exports.commands = (program, flecks) => {
|
|||
else {
|
||||
code = [
|
||||
code,
|
||||
`exports.dependencies = ['${fleck}'];\n`,
|
||||
`exports.dependencies = ['${packages.join("', '")}'];\n`,
|
||||
].join('\n');
|
||||
}
|
||||
await writeFile(bootstrapPath, code);
|
||||
}
|
||||
// Otherwise, assume we're in an application root.
|
||||
else {
|
||||
await addFleckToYml(fleck);
|
||||
await addPathsToYml(packages);
|
||||
}
|
||||
},
|
||||
},
|
||||
clean: {
|
||||
description: 'Remove node_modules, lock file, and build artifacts.',
|
||||
action: () => {
|
||||
rimraf.sync(join(FLECKS_CORE_ROOT, 'dist'));
|
||||
rimraf.sync(join(FLECKS_CORE_ROOT, 'node_modules'));
|
||||
switch (packageManager) {
|
||||
case 'yarn':
|
||||
rimraf.sync(join(FLECKS_CORE_ROOT, 'yarn.lock'));
|
||||
break;
|
||||
case 'bun':
|
||||
rimraf.sync(join(FLECKS_CORE_ROOT, 'bun.lockb'));
|
||||
break;
|
||||
case 'npm':
|
||||
rimraf.sync(join(FLECKS_CORE_ROOT, 'package-lock.json'));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
options: [
|
||||
program.createOption('-pm,--package-manager <binary>', 'package manager binary')
|
||||
.choices(['npm', 'bun', 'pnpm', 'yarn']),
|
||||
],
|
||||
action: async ({packageManager}) => {
|
||||
await Promise.all([
|
||||
rimraf(join(FLECKS_CORE_ROOT, 'dist')),
|
||||
rimraf(join(FLECKS_CORE_ROOT, 'node_modules')),
|
||||
rimraf(join(FLECKS_CORE_ROOT, lockFile(packageManager))),
|
||||
]);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -171,7 +165,7 @@ exports.commands = (program, flecks) => {
|
|||
options: [
|
||||
program.createOption('-d, --no-production', 'dev build'),
|
||||
program.createOption('-h, --hot', 'build with hot module reloading')
|
||||
.implies({production: false}),
|
||||
.implies({production: false, watch: true}),
|
||||
program.createOption('-w, --watch', 'watch for changes')
|
||||
.implies({production: false}),
|
||||
],
|
||||
|
@ -185,7 +179,7 @@ exports.commands = (program, flecks) => {
|
|||
debug('Building...', opts);
|
||||
const webpackConfig = await flecks.resolveBuildConfig('fleckspack.config.js');
|
||||
const cmd = [
|
||||
'npx', 'webpack',
|
||||
join(FLECKS_CORE_ROOT, 'node_modules', '.bin', 'webpack'),
|
||||
'--config', webpackConfig,
|
||||
'--mode', (production && !hot) ? 'production' : 'development',
|
||||
...((watch || hot) ? ['--watch'] : []),
|
||||
|
@ -217,7 +211,7 @@ exports.commands = (program, flecks) => {
|
|||
.map((pkg) => join(process.cwd(), pkg))
|
||||
.map(async (cwd) => {
|
||||
const cmd = [
|
||||
'npx', 'eslint',
|
||||
join(FLECKS_CORE_ROOT, 'node_modules', '.bin', 'eslint'),
|
||||
'--config', await flecks.resolveBuildConfig('eslint.config.js'),
|
||||
'.',
|
||||
];
|
||||
|
@ -260,7 +254,3 @@ exports.commands = (program, flecks) => {
|
|||
};
|
||||
return commands;
|
||||
};
|
||||
|
||||
exports.Argument = Argument;
|
||||
exports.Option = Option;
|
||||
exports.program = program;
|
||||
|
|
|
@ -49,10 +49,6 @@ exports.hooks = {
|
|||
'fleck.webpack.config.js',
|
||||
],
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* The package manager used for tasks.
|
||||
*/
|
||||
packageManager: 'npm',
|
||||
/**
|
||||
* Build targets to profile with `webpack.debug.ProfilingPlugin`.
|
||||
*/
|
||||
|
|
|
@ -1,32 +1,5 @@
|
|||
const {spawn} = require('child_process');
|
||||
|
||||
export {glob} from 'glob';
|
||||
|
||||
const D = require('../../build/debug');
|
||||
|
||||
const debug = D('@flecks/core/server');
|
||||
const debugSilly = debug.extend('silly');
|
||||
|
||||
export {JsonStream, transform} from '../../build/stream';
|
||||
|
||||
export const processCode = (child) => new Promise((resolve, reject) => {
|
||||
child.on('error', reject);
|
||||
child.on('exit', (code) => {
|
||||
child.off('error', reject);
|
||||
resolve(code);
|
||||
});
|
||||
});
|
||||
|
||||
export const spawnWith = (cmd, opts = {}) => {
|
||||
debug("spawning: '%s'", cmd.join(' '));
|
||||
debugSilly('with options: %O', opts);
|
||||
const child = spawn(cmd[0], cmd.slice(1), {
|
||||
stdio: 'inherit',
|
||||
...opts,
|
||||
env: {
|
||||
...process.env,
|
||||
...opts.env,
|
||||
},
|
||||
});
|
||||
return child;
|
||||
};
|
||||
export * from '../../build/stream';
|
||||
export * from './package-manager';
|
||||
export * from './process';
|
||||
|
|
100
packages/core/src/server/package-manager.js
Normal file
100
packages/core/src/server/package-manager.js
Normal file
|
@ -0,0 +1,100 @@
|
|||
import {processCode, spawnWith} from './process';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
const {
|
||||
npm_config_user_agent = 'npm',
|
||||
} = process.env;
|
||||
|
||||
export const inferPackageManager = () => npm_config_user_agent.split('/')[0];
|
||||
/* eslint-enable camelcase */
|
||||
|
||||
export const build = async ({cwd, packageManager = inferPackageManager()}) => {
|
||||
let args;
|
||||
switch (packageManager) {
|
||||
case 'bun':
|
||||
args = ['bun', 'run', 'build'];
|
||||
break;
|
||||
case 'npm':
|
||||
args = ['npm', 'run', 'build'];
|
||||
break;
|
||||
case 'pnpm':
|
||||
args = ['pnpm', 'run', 'build'];
|
||||
break;
|
||||
case 'yarn':
|
||||
args = ['yarn', 'run', 'build'];
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return args && processCode(spawnWith(args, {cwd}));
|
||||
};
|
||||
|
||||
export const add = async ({dev, packageManager = inferPackageManager(), packages}) => {
|
||||
let args;
|
||||
switch (packageManager) {
|
||||
case 'bun':
|
||||
args = [
|
||||
'bun', 'add',
|
||||
...(dev ? ['--dev'] : []),
|
||||
...packages,
|
||||
];
|
||||
break;
|
||||
case 'npm':
|
||||
args = [
|
||||
'npm', 'install',
|
||||
...(dev ? ['--save-dev'] : []),
|
||||
...packages,
|
||||
];
|
||||
break;
|
||||
case 'pnpm':
|
||||
args = [
|
||||
'pnpm', 'add',
|
||||
...(dev ? ['--save-dev'] : []),
|
||||
...packages,
|
||||
];
|
||||
break;
|
||||
case 'yarn':
|
||||
args = [
|
||||
'yarn', 'add',
|
||||
...(dev ? ['--dev'] : []),
|
||||
...packages,
|
||||
];
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return args && processCode(spawnWith(args));
|
||||
};
|
||||
|
||||
export const install = async ({cwd, packageManager = inferPackageManager()}) => {
|
||||
let args;
|
||||
switch (packageManager) {
|
||||
case 'bun':
|
||||
args = ['bun', 'install'];
|
||||
break;
|
||||
case 'npm':
|
||||
args = ['npm', 'install'];
|
||||
break;
|
||||
case 'pnpm':
|
||||
args = ['pnpm', 'install'];
|
||||
break;
|
||||
case 'yarn':
|
||||
args = ['yarn', 'install'];
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return args && processCode(spawnWith(args, {cwd}));
|
||||
};
|
||||
|
||||
export const lockFile = (packageManager = inferPackageManager()) => {
|
||||
switch (packageManager) {
|
||||
case 'bun':
|
||||
return 'bun.lockb';
|
||||
case 'npm':
|
||||
return 'package-lock.json';
|
||||
case 'pnpm':
|
||||
return 'pnpm-lock.yaml';
|
||||
case 'yarn':
|
||||
return 'yarn.lock';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
};
|
28
packages/core/src/server/process.js
Normal file
28
packages/core/src/server/process.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import {spawn} from 'child_process';
|
||||
|
||||
import D from '../../build/debug';
|
||||
|
||||
const debug = D('@flecks/core/server');
|
||||
const debugSilly = debug.extend('silly');
|
||||
|
||||
export const processCode = (child) => new Promise((resolve, reject) => {
|
||||
child.on('error', reject);
|
||||
child.on('exit', (code) => {
|
||||
child.off('error', reject);
|
||||
resolve(code);
|
||||
});
|
||||
});
|
||||
|
||||
export const spawnWith = (cmd, opts = {}) => {
|
||||
debug("spawning: '%s'", cmd.join(' '));
|
||||
debugSilly('with options: %O', opts);
|
||||
const child = spawn(cmd[0], cmd.slice(1), {
|
||||
stdio: 'inherit',
|
||||
...opts,
|
||||
env: {
|
||||
...process.env,
|
||||
...opts.env,
|
||||
},
|
||||
});
|
||||
return child;
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
const {processCode, spawnWith} = require('@flecks/core/server');
|
||||
|
||||
module.exports = async (packageManager, cwd) => {
|
||||
const code = await processCode(spawnWith([packageManager, 'install'], {cwd}));
|
||||
if (0 !== code) {
|
||||
return code;
|
||||
}
|
||||
return processCode(spawnWith([packageManager, 'run', 'build'], {cwd}));
|
||||
};
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
const {join} = require('path');
|
||||
|
||||
const {transform} = require('@flecks/core/server');
|
||||
const {
|
||||
build,
|
||||
install,
|
||||
transform,
|
||||
} = require('@flecks/core/server');
|
||||
const {program} = require('commander');
|
||||
const {dump: dumpYml, load: loadYml} = require('js-yaml');
|
||||
const validate = require('validate-npm-package-name');
|
||||
|
||||
const build = require('./build');
|
||||
// const build = require('./build');
|
||||
const {move, testDestination} = require('./move');
|
||||
|
||||
const {
|
||||
|
@ -18,8 +22,7 @@ const {
|
|||
program.argument('<app>', 'name of the app to create');
|
||||
program.addOption(
|
||||
program.createOption('-pm,--package-manager <binary>', 'package manager binary')
|
||||
.choices(['npm', 'bun', 'yarn'])
|
||||
.default('npm'),
|
||||
.choices(['npm', 'bun', 'pnpm', 'yarn']),
|
||||
);
|
||||
program.action(async (app, {packageManager}) => {
|
||||
try {
|
||||
|
@ -42,16 +45,14 @@ const {
|
|||
transform((chunk, encoding, done, stream) => {
|
||||
const yml = loadYml(chunk);
|
||||
yml['@flecks/core'].id = app;
|
||||
if ('npm' !== packageManager) {
|
||||
yml['@flecks/build'].packageManager = packageManager;
|
||||
}
|
||||
stream.push(dumpYml(yml, {forceQuotes: true, sortKeys: true}));
|
||||
done();
|
||||
}),
|
||||
);
|
||||
// Write the tree.
|
||||
await fileTree.writeTo(destination);
|
||||
await build(packageManager, destination);
|
||||
await install({cwd: destination, packageManager});
|
||||
await build({cwd: destination, packageManager});
|
||||
}
|
||||
catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
const {stat} = require('fs/promises');
|
||||
const {join} = require('path');
|
||||
|
||||
const Build = require('@flecks/build/build/build');
|
||||
const addFleckToYml = require('@flecks/build/build/add-fleck-to-yml');
|
||||
const {program} = require('@flecks/build/build/commands');
|
||||
const {transform} = require('@flecks/core/server');
|
||||
const build = require('@flecks/create-app/build/build');
|
||||
const addPathsToYml = require('@flecks/build/build/add-paths-to-yml');
|
||||
const {program} = require('commander');
|
||||
const {
|
||||
build,
|
||||
install,
|
||||
transform,
|
||||
} = require('@flecks/core/server');
|
||||
const {move, testDestination} = require('@flecks/create-app/build/move');
|
||||
const {validate} = require('@flecks/create-app/server');
|
||||
|
||||
|
@ -64,11 +66,12 @@ const target = async (fleck) => {
|
|||
program.argument('<fleck>', 'name of the fleck to create');
|
||||
program.option('--no-add', 'do not add an entry to `build/flecks.yml`');
|
||||
program.option('--no-alias', 'do not alias the fleck in `build/flecks.yml`');
|
||||
program.action(async (fleck, o) => {
|
||||
const {alias, add} = o;
|
||||
program.addOption(
|
||||
program.createOption('-pm,--package-manager <binary>', 'package manager binary')
|
||||
.choices(['npm', 'bun', 'pnpm', 'yarn']),
|
||||
);
|
||||
program.action(async (fleck, {alias, add, packageManager}) => {
|
||||
try {
|
||||
const flecks = await Build.from();
|
||||
const {packageManager} = flecks.get('@flecks/build');
|
||||
const isMonorepo = await checkIsMonorepo();
|
||||
const [scope, pkg] = await target(fleck);
|
||||
const name = [scope, pkg].filter((e) => !!e).join('/');
|
||||
|
@ -97,9 +100,11 @@ const target = async (fleck) => {
|
|||
}
|
||||
// Write the tree.
|
||||
await fileTree.writeTo(destination);
|
||||
await build(packageManager, destination);
|
||||
// Install and build.
|
||||
await install({cwd: destination, packageManager});
|
||||
await build({cwd: destination, packageManager});
|
||||
if (isMonorepo && add) {
|
||||
await addFleckToYml(...[name].concat(alias ? pkg : []));
|
||||
await addPathsToYml([[name].concat(alias ? `./packages/${pkg}` : []).join(':')]);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
"dependencies": {
|
||||
"@flecks/build": "^3.2.0",
|
||||
"@flecks/core": "^3.2.0",
|
||||
"@flecks/create-app": "^3.2.0"
|
||||
"@flecks/create-app": "^3.2.0",
|
||||
"commander": "11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@flecks/fleck": "^3.2.0"
|
||||
|
|
Loading…
Reference in New Issue
Block a user