feat: package manager (and bun)
This commit is contained in:
parent
7198ad998e
commit
16934d55c9
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -117,6 +117,8 @@ dist
|
|||
|
||||
# local
|
||||
/yarn.lock
|
||||
/bun.lockb
|
||||
|
||||
# package-locals
|
||||
/packages/*/yarn.lock
|
||||
/packages/*/bun.lockb
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build": "NODE_PATH=./node_modules webpack --config ./build/webpack.config.js --mode production",
|
||||
"clean": "rm -rf dist node_modules yarn.lock && yarn",
|
||||
"clean": "rm -rf dist bun.lockb && bun install",
|
||||
"lint": "NODE_PATH=./node_modules eslint --config ./build/eslint.config.js .",
|
||||
"postversion": "cp package.json dist",
|
||||
"test": "npm run build && mocha -t 10000 --colors ./dist/test.js"
|
||||
|
|
|
@ -17,7 +17,7 @@ const debug = D('@flecks/core/commands');
|
|||
const debugSilly = debug.extend('silly');
|
||||
const flecksRoot = normalize(FLECKS_CORE_ROOT);
|
||||
|
||||
export {Argument};
|
||||
export {Argument, Option, program} from 'commander';
|
||||
|
||||
export const processCode = (child) => new Promise((resolve, reject) => {
|
||||
child.on('error', reject);
|
||||
|
@ -45,45 +45,46 @@ export const spawnWith = (cmd, opts = {}) => {
|
|||
};
|
||||
|
||||
export default (program, flecks) => {
|
||||
const {packageManager} = flecks.get('@flecks/core/server');
|
||||
const commands = {
|
||||
add: {
|
||||
args: [
|
||||
new Argument('<fleck>>', 'fleck'),
|
||||
new Argument('<fleck>', 'fleck'),
|
||||
],
|
||||
description: 'add a fleck to your application',
|
||||
action: async (fleck, opts) => {
|
||||
const {
|
||||
noYarn,
|
||||
} = opts;
|
||||
await processCode(
|
||||
noYarn
|
||||
? spawn('npm', ['install', fleck], {stdio: 'inherit'})
|
||||
: spawn('yarn', ['add', fleck], {stdio: 'inherit'}),
|
||||
);
|
||||
const args = [];
|
||||
if ('yarn' === packageManager) {
|
||||
args.push('yarn', ['add', fleck]);
|
||||
}
|
||||
else {
|
||||
args.push(packageManager, ['install', fleck]);
|
||||
}
|
||||
args.push({stdio: 'inherit'});
|
||||
await processCode(spawn(...args));
|
||||
await Flecks.addFleckToYml(fleck);
|
||||
},
|
||||
options: [
|
||||
['--no-yarn', 'use npm instead of yarn'],
|
||||
],
|
||||
},
|
||||
clean: {
|
||||
description: 'remove node_modules, lock file, build artifacts, then reinstall',
|
||||
action: (opts) => {
|
||||
const {
|
||||
noYarn,
|
||||
} = opts;
|
||||
rimraf.sync(join(flecksRoot, 'dist'));
|
||||
rimraf.sync(join(flecksRoot, 'node_modules'));
|
||||
if (noYarn) {
|
||||
rimraf.sync(join(flecksRoot, 'package-lock.json'));
|
||||
return spawn('npm', ['install'], {stdio: 'inherit'});
|
||||
switch (packageManager) {
|
||||
case 'yarn':
|
||||
rimraf.sync(join(flecksRoot, 'yarn.lock'));
|
||||
break;
|
||||
case 'bun':
|
||||
rimraf.sync(join(flecksRoot, 'bun.lockb'));
|
||||
break;
|
||||
case 'npm':
|
||||
rimraf.sync(join(flecksRoot, 'package-lock.json'));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rimraf.sync(join(flecksRoot, 'yarn.lock'));
|
||||
return spawn('yarn', [], {stdio: 'inherit'});
|
||||
return spawn(packageManager, ['install'], {stdio: 'inherit'});
|
||||
},
|
||||
options: [
|
||||
['--no-yarn', 'use npm instead of yarn'],
|
||||
],
|
||||
},
|
||||
};
|
||||
const targets = flatten(flecks.invokeFlat('@flecks/core.targets'));
|
||||
|
|
|
@ -21,7 +21,9 @@ export {dump as dumpYml, load as loadYml} from 'js-yaml';
|
|||
export {
|
||||
Argument,
|
||||
default as commands,
|
||||
Option,
|
||||
processCode,
|
||||
program,
|
||||
spawnWith,
|
||||
} from './commands';
|
||||
export {default as Flecks} from './flecks';
|
||||
|
@ -101,6 +103,10 @@ export const hooks = {
|
|||
* Build targets to exclude from ESLint.
|
||||
*/
|
||||
'eslint.exclude': [],
|
||||
/**
|
||||
* The package manager used for tasks.
|
||||
*/
|
||||
packageManager: 'npm',
|
||||
/**
|
||||
* Build targets to profile with `webpack.debug.ProfilingPlugin`.
|
||||
*/
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import {processCode, spawnWith} from '@flecks/core/server';
|
||||
|
||||
export default async (cwd) => {
|
||||
const code = await processCode(spawnWith(['yarn'], {cwd}));
|
||||
export default async (packageManager, cwd) => {
|
||||
const code = await processCode(spawnWith([packageManager, 'install'], {cwd}));
|
||||
if (0 !== code) {
|
||||
return code;
|
||||
}
|
||||
return processCode(spawnWith(['yarn', 'build'], {cwd}));
|
||||
return processCode(spawnWith([packageManager, 'run', 'build'], {cwd}));
|
||||
};
|
||||
|
|
|
@ -1,39 +1,72 @@
|
|||
import {join, normalize} from 'path';
|
||||
import {join} from 'path';
|
||||
|
||||
import {Flecks} from '@flecks/core/server';
|
||||
import {
|
||||
dumpYml,
|
||||
Flecks,
|
||||
loadYml,
|
||||
Option,
|
||||
program,
|
||||
transform,
|
||||
} from '@flecks/core/server';
|
||||
import validate from 'validate-npm-package-name';
|
||||
|
||||
import build from './build';
|
||||
import move from './move';
|
||||
import move, {testDestination} from './move';
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
} = process.env;
|
||||
|
||||
const cwd = normalize(FLECKS_CORE_ROOT);
|
||||
|
||||
const create = async (flecks) => {
|
||||
let name = process.argv[2];
|
||||
const {errors} = validate(name);
|
||||
if (errors) {
|
||||
throw new Error(`@flecks/create-app: invalid app name: ${errors.join(', ')}`);
|
||||
}
|
||||
const destination = join(cwd, name);
|
||||
if (!name.startsWith('@')) {
|
||||
name = `@${name}/monorepo`;
|
||||
}
|
||||
await move(name, join(__dirname, 'template'), destination, 'app', flecks);
|
||||
await build(destination);
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const flecks = await Flecks.bootstrap();
|
||||
try {
|
||||
await create(flecks);
|
||||
}
|
||||
catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error.message);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
program.argument('<app>', 'name of the app to create');
|
||||
program.addOption(
|
||||
new Option('--package-manager <binary>', 'package manager binary')
|
||||
.choices(['npm', 'bun', 'yarn'])
|
||||
.default('npm'),
|
||||
);
|
||||
program.action(async (app, {packageManager}) => {
|
||||
const flecks = await Flecks.bootstrap({
|
||||
config: {
|
||||
'@flecks/core': {},
|
||||
'@flecks/core/server': {packageManager},
|
||||
'@flecks/create-app': {},
|
||||
'@flecks/fleck': {},
|
||||
},
|
||||
});
|
||||
try {
|
||||
const {errors} = validate(app);
|
||||
if (errors) {
|
||||
throw new Error(`@flecks/create-app: invalid app name: ${errors.join(', ')}`);
|
||||
}
|
||||
const destination = join(FLECKS_CORE_ROOT, app);
|
||||
if (!app.startsWith('@')) {
|
||||
app = `@${app}/monorepo`;
|
||||
}
|
||||
if (!await testDestination(destination)) {
|
||||
const error = new Error(
|
||||
`@flecks/create-app: destination '${destination} already exists: aborting`,
|
||||
);
|
||||
error.code = 129;
|
||||
throw error;
|
||||
}
|
||||
const fileTree = await move(app, join(__dirname, 'template'), 'app', flecks);
|
||||
fileTree.pipe(
|
||||
'build/flecks.yml',
|
||||
transform((chunk, encoding, done, stream) => {
|
||||
const yml = loadYml(chunk);
|
||||
yml['@flecks/core/server'] = {packageManager};
|
||||
stream.push(dumpYml(yml, {sortKeys: true}));
|
||||
done();
|
||||
}),
|
||||
);
|
||||
// Write the tree.
|
||||
await fileTree.writeTo(destination);
|
||||
await build(packageManager, destination);
|
||||
}
|
||||
catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
await program.parseAsync(process.argv);
|
||||
})();
|
||||
|
|
|
@ -3,11 +3,14 @@ import {
|
|||
} from 'fs/promises';
|
||||
import {basename, dirname, join} from 'path';
|
||||
|
||||
import {JsonStream, transform} from '@flecks/core/server';
|
||||
import {
|
||||
JsonStream,
|
||||
transform,
|
||||
} from '@flecks/core/server';
|
||||
|
||||
import FileTree from './tree';
|
||||
|
||||
const testDestination = async (destination) => {
|
||||
export const testDestination = async (destination) => {
|
||||
try {
|
||||
await stat(destination);
|
||||
return false;
|
||||
|
@ -20,14 +23,7 @@ const testDestination = async (destination) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default async (name, source, destination, type, flecks) => {
|
||||
if (!await testDestination(destination)) {
|
||||
const error = new Error(
|
||||
`@flecks/create-fleck: destination '${destination} already exists: aborting`,
|
||||
);
|
||||
error.code = 129;
|
||||
throw error;
|
||||
}
|
||||
export default async (name, source, type, flecks) => {
|
||||
const fileTree = await FileTree.loadFrom(source);
|
||||
// Renamed to avoid conflicts.
|
||||
const {files} = fileTree;
|
||||
|
@ -56,6 +52,5 @@ export default async (name, source, destination, type, flecks) => {
|
|||
.forEach((path) => {
|
||||
fileTree.pipe(path, new JsonStream.PrettyPrint());
|
||||
});
|
||||
// Write the tree.
|
||||
await fileTree.writeTo(destination);
|
||||
return fileTree;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export {default as validate} from 'validate-npm-package-name';
|
||||
|
||||
export {default as build} from './build';
|
||||
export {default as move} from './move';
|
||||
export {default as move, testDestination} from './move';
|
||||
export {default as FileTree} from './tree';
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@flecks/core": "^2.0.3",
|
||||
"@flecks/create-app": "^2.0.3",
|
||||
"@inquirer/prompts": "^3.3.0"
|
||||
"@flecks/create-app": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@flecks/fleck": "^2.0.3"
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
import {stat} from 'fs/promises';
|
||||
import {join, normalize} from 'path';
|
||||
import {join} from 'path';
|
||||
|
||||
import {build, move, validate} from '@flecks/create-app/server';
|
||||
import {Flecks} from '@flecks/core/server';
|
||||
import {confirm} from '@inquirer/prompts';
|
||||
import {
|
||||
build,
|
||||
move,
|
||||
testDestination,
|
||||
validate,
|
||||
} from '@flecks/create-app/server';
|
||||
import {Flecks, program} from '@flecks/core/server';
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
} = process.env;
|
||||
|
||||
const cwd = normalize(FLECKS_CORE_ROOT);
|
||||
|
||||
const checkIsMonorepo = async (cwd) => {
|
||||
const checkIsMonorepo = async () => {
|
||||
try {
|
||||
await stat(join(cwd, 'packages'));
|
||||
await stat(join(FLECKS_CORE_ROOT, 'packages'));
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
|
@ -24,9 +26,9 @@ const checkIsMonorepo = async (cwd) => {
|
|||
}
|
||||
};
|
||||
|
||||
const monorepoScope = async (cwd) => {
|
||||
const monorepoScope = async () => {
|
||||
try {
|
||||
const {name} = __non_webpack_require__(join(cwd, 'package.json'));
|
||||
const {name} = __non_webpack_require__(join(FLECKS_CORE_ROOT, 'package.json'));
|
||||
const [scope] = name.split('/');
|
||||
return scope;
|
||||
}
|
||||
|
@ -38,45 +40,57 @@ const monorepoScope = async (cwd) => {
|
|||
}
|
||||
};
|
||||
|
||||
const target = async (name) => {
|
||||
const {errors} = validate(name);
|
||||
const target = async (fleck) => {
|
||||
const {errors} = validate(fleck);
|
||||
if (errors) {
|
||||
throw new Error(`@flecks/create-fleck: invalid fleck name: ${errors.join(', ')}`);
|
||||
}
|
||||
const parts = name.split('/');
|
||||
const parts = fleck.split('/');
|
||||
let pkg;
|
||||
let scope;
|
||||
if (1 === parts.length) {
|
||||
pkg = name;
|
||||
if (await checkIsMonorepo(cwd)) {
|
||||
scope = await monorepoScope(cwd);
|
||||
pkg = fleck;
|
||||
if (await checkIsMonorepo()) {
|
||||
scope = await monorepoScope();
|
||||
}
|
||||
return [scope, pkg];
|
||||
}
|
||||
return parts;
|
||||
};
|
||||
|
||||
const create = async (flecks) => {
|
||||
const isMonorepo = await checkIsMonorepo(cwd);
|
||||
const [scope, pkg] = await target(process.argv[2]);
|
||||
const path = scope && isMonorepo ? join(cwd, 'packages') : cwd;
|
||||
const name = [scope, pkg].filter((e) => !!e).join('/');
|
||||
const destination = join(path, pkg);
|
||||
await move(name, join(__dirname, 'template'), destination, 'fleck', flecks);
|
||||
await build(destination);
|
||||
if (isMonorepo && await confirm({message: 'Add fleck to `build/flecks.yml`?'})) {
|
||||
await Flecks.addFleckToYml(name, pkg);
|
||||
}
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const flecks = await Flecks.bootstrap();
|
||||
try {
|
||||
await create(flecks);
|
||||
}
|
||||
catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error.message);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
program.argument('<fleck>', 'name of the fleck to create');
|
||||
program.option('--no-add', 'do not add an entry to `build/flecks.yml`');
|
||||
program.action(async (fleck, {add}) => {
|
||||
try {
|
||||
const flecks = await Flecks.bootstrap();
|
||||
const {packageManager} = flecks.get('@flecks/core/server');
|
||||
const isMonorepo = await checkIsMonorepo();
|
||||
const [scope, pkg] = await target(fleck);
|
||||
const name = [scope, pkg].filter((e) => !!e).join('/');
|
||||
const destination = join(
|
||||
join(...[FLECKS_CORE_ROOT].concat(isMonorepo ? ['packages'] : [])),
|
||||
pkg,
|
||||
);
|
||||
if (!await testDestination(destination)) {
|
||||
const error = new Error(
|
||||
`@flecks/create-fleck: destination '${destination} already exists: aborting`,
|
||||
);
|
||||
error.code = 129;
|
||||
throw error;
|
||||
}
|
||||
const fileTree = await move(name, join(__dirname, 'template'), 'fleck', flecks);
|
||||
// Write the tree.
|
||||
await fileTree.writeTo(destination);
|
||||
await build(packageManager, destination);
|
||||
if (isMonorepo && add) {
|
||||
await Flecks.addFleckToYml(name, pkg);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Creation failed:', error);
|
||||
}
|
||||
});
|
||||
await program.parseAsync(process.argv);
|
||||
})();
|
||||
|
|
Loading…
Reference in New Issue
Block a user