Skip to content

Commit

Permalink
Merge pull request #201 from form8ion/alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
travi authored May 25, 2022
2 parents eaadb6c + 97290f4 commit 46fb4ae
Show file tree
Hide file tree
Showing 18 changed files with 130 additions and 38 deletions.
5 changes: 5 additions & 0 deletions docs/api/scaffold.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ for defining [package-type plugin options](https://github.com/form8ion/awesome#p
A [`choices` object](https://github.com/form8ion/javascript-core#choices-object-required)
for defining monorepo-type plugin options

### `packageBundlers` __object__ (_optional_)

A [`choices` object](https://github.com/form8ion/javascript-core#choices-object-required)
for defining package bundler options

### `unitTestFrameworks` __object__ (_required_)

A [`choices` object](https://github.com/form8ion/javascript-core#choices-object-required)
Expand Down
1 change: 1 addition & 0 deletions src/options-validator-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ suite('options validator', () => {
hosts: {},
applicationTypes: {},
packageTypes: {},
packageBundlers: {},
registries: {}
}
);
Expand Down
1 change: 1 addition & 0 deletions src/prompts/question-names.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const questionNames = {
UNIT_TEST_FRAMEWORK: 'unitTestFramework',
NODE_VERSION_CATEGORY: 'nodeVersionCategory',
PACKAGE_MANAGER: 'packageManager',
PACKAGE_BUNDLER: 'packageBundler',
PROJECT_TYPE: 'projectType',
PROJECT_TYPE_CHOICE: 'projectTypeChoice',
SHOULD_BE_SCOPED: 'shouldBeScoped',
Expand Down
4 changes: 4 additions & 0 deletions src/scaffolder/project-type/options-schemas-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@ suite('project-type options validation', () => {
test('that a provided bundler scaffolder is valid if an options object is provided', () => {
validateOptions(packageBundlersSchema, {[key]: {scaffolder: options => options}});
});

test('that an empty object is provided by default', async () => {
assert.deepEqual(validateOptions(packageBundlersSchema, undefined), {});
});
});
});
2 changes: 1 addition & 1 deletion src/scaffolder/project-type/options-schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import * as joi from 'joi';

export const packageBundlersSchema = joi.object().pattern(/^/, joi.object({
scaffolder: joi.func().arity(1).required()
}));
})).default({});
29 changes: 17 additions & 12 deletions src/scaffolder/project-type/package/build-details-test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {promises as fsPromises, promises as fs} from 'fs';
import mustache from 'mustache';
import {dialects, projectTypes} from '@form8ion/javascript-core';
import * as rollupScaffolder from '@form8ion/rollup';
import * as jsCore from '@form8ion/javascript-core';

import {assert} from 'chai';
import sinon from 'sinon';
Expand All @@ -11,6 +10,7 @@ import * as touch from '../../../../thirdparty-wrappers/touch';
import * as mkdir from '../../../../thirdparty-wrappers/make-dir';
import * as camelcase from '../../../../thirdparty-wrappers/camelcase';
import * as templatePath from '../../../template-path';
import * as bundlerPrompt from './prompt';
import buildDetails from './build-details';

suite('package build details', () => {
Expand All @@ -19,11 +19,13 @@ suite('package build details', () => {
const projectName = any.word();
const pathToExample = `${projectRoot}/example.js`;
const pathToCreatedSrcDirectory = any.string();
const rollupResults = any.simpleObject();
const bundlerResults = any.simpleObject();
const exampleContent = any.string();
const pathToExampleTemplate = any.string();
const exampleTemplateContent = any.string();
const camelizedProjectName = any.word();
const packageBundlers = any.simpleObject();
const decisions = any.simpleObject();

setup(() => {
sandbox = sinon.createSandbox();
Expand All @@ -33,9 +35,10 @@ suite('package build details', () => {
sandbox.stub(touch, 'default');
sandbox.stub(mkdir, 'default');
sandbox.stub(templatePath, 'default');
sandbox.stub(rollupScaffolder, 'scaffold');
sandbox.stub(jsCore, 'scaffoldChoice');
sandbox.stub(mustache, 'render');
sandbox.stub(camelcase, 'default');
sandbox.stub(bundlerPrompt, 'default');

mkdir.default.withArgs(`${projectRoot}/src`).resolves(pathToCreatedSrcDirectory);
templatePath.default.withArgs('example.mustache').returns(pathToExampleTemplate);
Expand All @@ -47,23 +50,25 @@ suite('package build details', () => {
teardown(() => sandbox.restore());

test('that common-js project is defined correctly', async () => {
assert.deepEqual(await buildDetails({dialect: dialects.COMMON_JS, projectRoot, projectName}), {});
assert.deepEqual(await buildDetails({dialect: jsCore.dialects.COMMON_JS, projectRoot, projectName}), {});
assert.calledWith(fsPromises.writeFile, pathToExample, `const ${camelizedProjectName} = require('.');\n`);
assert.calledWith(touch.default, `${projectRoot}/index.js`);
});

test('that a modern-js project is defined correctly', async () => {
const dialect = dialects.BABEL;
rollupScaffolder.scaffold
.withArgs({projectRoot, dialect, projectType: projectTypes.PACKAGE})
.resolves(rollupResults);
const dialect = jsCore.dialects.BABEL;
const chosenBundler = any.word();
bundlerPrompt.default.withArgs({bundlers: packageBundlers, decisions}).resolves(chosenBundler);
jsCore.scaffoldChoice
.withArgs(packageBundlers, chosenBundler, {projectRoot, dialect, projectType: jsCore.projectTypes.PACKAGE})
.resolves(bundlerResults);

const results = await buildDetails({dialect, projectRoot, projectName});
const results = await buildDetails({dialect, projectRoot, projectName, packageBundlers, decisions});

assert.deepEqual(
results,
{
...rollupResults,
...bundlerResults,
devDependencies: ['rimraf'],
scripts: {
clean: 'rimraf ./lib',
Expand All @@ -84,7 +89,7 @@ suite('package build details', () => {
const packageName = any.word();

const {badges} = await buildDetails({
dialect: dialects.BABEL,
dialect: jsCore.dialects.BABEL,
projectRoot,
projectName,
packageName,
Expand Down
22 changes: 16 additions & 6 deletions src/scaffolder/project-type/package/build-details.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {promises as fs} from 'fs';
import deepmerge from 'deepmerge';
import mustache from 'mustache';
import {dialects, projectTypes} from '@form8ion/javascript-core';
import {scaffold as scaffoldRollup} from '@form8ion/rollup';
import {dialects, projectTypes, scaffoldChoice as scaffoldChosenBundler} from '@form8ion/javascript-core';

import camelcase from '../../../../thirdparty-wrappers/camelcase';
import mkdir from '../../../../thirdparty-wrappers/make-dir';
import touch from '../../../../thirdparty-wrappers/touch';
import chooseBundler from './prompt';
import determinePathToTemplateFile from '../../../template-path';

const defaultBuildDirectory = 'lib';
Expand All @@ -30,18 +30,28 @@ async function buildDetailsForCommonJsProject({projectRoot, projectName}) {
return {};
}

export default async function ({projectRoot, projectName, visibility, packageName, dialect}) {
export default async function ({
projectRoot,
projectName,
visibility,
packageName,
packageBundlers,
dialect,
decisions
}) {
if (dialects.COMMON_JS === dialect) return buildDetailsForCommonJsProject({projectRoot, projectName});

const chosenBundler = await chooseBundler({bundlers: packageBundlers, decisions});

const pathToCreatedSrcDirectory = await mkdir(`${projectRoot}/src`);
const [rollupResults] = await Promise.all([
scaffoldRollup({projectRoot, dialect, projectType: projectTypes.PACKAGE}),
const [bundlerResults] = await Promise.all([
scaffoldChosenBundler(packageBundlers, chosenBundler, {projectRoot, dialect, projectType: projectTypes.PACKAGE}),
await createExample(projectRoot, projectName),
touch(`${pathToCreatedSrcDirectory}/index.js`)
]);

return deepmerge(
rollupResults,
bundlerResults,
{
devDependencies: ['rimraf'],
scripts: {
Expand Down
40 changes: 40 additions & 0 deletions src/scaffolder/project-type/package/prompt-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import inquirer from 'inquirer';
import * as prompts from '@form8ion/overridable-prompts';
import any from '@travi/any';
import {assert} from 'chai';
import sinon from 'sinon';
import {questionNames} from '../../../prompts/question-names';
import prompt from './prompt';

suite('bundler prompt', () => {
let sandbox;

setup(() => {
sandbox = sinon.createSandbox();

sandbox.stub(prompts, 'prompt');
});

teardown(() => sandbox.restore());

test('that the choice of package bundlers is presented', async () => {
const chosenType = any.word();
const decisions = any.simpleObject();
const answers = {...any.simpleObject(), [questionNames.PACKAGE_BUNDLER]: chosenType};
const bundlers = any.simpleObject();
prompts.prompt
.withArgs([{
name: questionNames.PACKAGE_BUNDLER,
type: 'list',
message: 'Which bundler should be used?',
choices: [...Object.keys(bundlers), new inquirer.Separator(), 'Other']
}], decisions)
.resolves(answers);

assert.equal(await prompt({bundlers, decisions}), chosenType);
});

test('that the prompt is skipped and `Other` is returned when no options ar provided ', async () => {
assert.equal(await prompt({bundlers: {}}), 'Other');
});
});
16 changes: 16 additions & 0 deletions src/scaffolder/project-type/package/prompt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Separator} from 'inquirer';
import {prompt} from '@form8ion/overridable-prompts';
import {questionNames} from '../../../prompts/question-names';

export default async function ({bundlers, decisions}) {
if (!Object.keys(bundlers).length) return 'Other';

const answers = await prompt([{
name: questionNames.PACKAGE_BUNDLER,
type: 'list',
message: 'Which bundler should be used?',
choices: [...Object.keys(bundlers), new Separator(), 'Other']
}], decisions);

return answers[questionNames.PACKAGE_BUNDLER];
}
13 changes: 9 additions & 4 deletions src/scaffolder/project-type/package/scaffolder-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ suite('package project-type', () => {
let sandbox;
const projectRoot = any.string();
const packageTypes = any.simpleObject();
const packageBundlers = any.simpleObject();
const projectName = any.word();
const packageName = any.word();
const packageManager = any.word();
Expand Down Expand Up @@ -63,7 +64,7 @@ suite('package project-type', () => {
const dialect = jsCore.dialects.BABEL;
defineBadges.default.withArgs(packageName, visibility).returns(badges);
buildDetails.default
.withArgs({projectRoot, projectName, visibility, packageName, dialect})
.withArgs({projectRoot, projectName, packageBundlers, visibility, packageName, dialect, decisions})
.resolves(buildDetailsResults);

assert.deepEqual(
Expand All @@ -75,6 +76,7 @@ suite('package project-type', () => {
visibility,
scope,
packageTypes,
packageBundlers,
tests,
decisions,
dialect
Expand Down Expand Up @@ -104,7 +106,7 @@ suite('package project-type', () => {
const dialect = jsCore.dialects.ESM;
defineBadges.default.withArgs(packageName, visibility).returns(badges);
buildDetails.default
.withArgs({projectRoot, projectName, visibility, packageName, dialect})
.withArgs({projectRoot, projectName, packageBundlers, visibility, packageName, dialect, decisions})
.resolves(buildDetailsResults);

assert.deepEqual(
Expand All @@ -117,6 +119,7 @@ suite('package project-type', () => {
scope,
packageManager,
packageTypes,
packageBundlers,
decisions,
tests
}),
Expand Down Expand Up @@ -144,7 +147,7 @@ suite('package project-type', () => {
const dialect = jsCore.dialects.TYPESCRIPT;
defineBadges.default.withArgs(packageName, visibility).returns(badges);
buildDetails.default
.withArgs({projectRoot, projectName, visibility, packageName, dialect})
.withArgs({projectRoot, projectName, packageBundlers, visibility, packageName, dialect, decisions})
.resolves(buildDetailsResults);

assert.deepEqual(
Expand All @@ -156,6 +159,7 @@ suite('package project-type', () => {
visibility,
scope,
packageTypes,
packageBundlers,
tests,
decisions,
dialect
Expand Down Expand Up @@ -185,7 +189,7 @@ suite('package project-type', () => {
const dialect = jsCore.dialects.COMMON_JS;
defineBadges.default.withArgs(packageName, visibility).returns(badges);
buildDetails.default
.withArgs({projectRoot, projectName, visibility, packageName, dialect})
.withArgs({projectRoot, projectName, packageBundlers, visibility, packageName, dialect, decisions})
.resolves(buildDetailsResults);

assert.deepEqual(
Expand All @@ -198,6 +202,7 @@ suite('package project-type', () => {
scope,
decisions,
packageTypes,
packageBundlers,
tests,
dialect
}),
Expand Down
11 changes: 10 additions & 1 deletion src/scaffolder/project-type/package/scaffolder.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,23 @@ export default async function ({
visibility,
scope,
packageTypes,
packageBundlers,
tests,
decisions,
dialect,
publishRegistry
}) {
info('Scaffolding Package Details');

const detailsForBuild = await buildDetails({projectRoot, projectName, visibility, packageName, dialect});
const detailsForBuild = await buildDetails({
projectRoot,
projectName,
packageBundlers,
visibility,
packageName,
dialect,
decisions
});
const details = {
...dialects.BABEL === dialect && {
packageProperties: {
Expand Down
3 changes: 3 additions & 0 deletions src/scaffolder/project-type/scaffolder-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ suite('project-type scaffolder', () => {
test('that the package-type scaffolder is applied when the project-type is `Package`', async () => {
const scope = any.word();
const packageTypes = any.simpleObject();
const packageBundlers = any.simpleObject();

packageTypeScaffolder.default
.withArgs({
Expand All @@ -46,6 +47,7 @@ suite('project-type scaffolder', () => {
visibility,
scope,
packageTypes,
packageBundlers,
tests,
vcs,
decisions,
Expand All @@ -64,6 +66,7 @@ suite('project-type scaffolder', () => {
visibility,
scope,
packageTypes,
packageBundlers,
tests,
vcs,
decisions,
Expand Down
2 changes: 2 additions & 0 deletions src/scaffolder/project-type/scaffolder.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default async function ({
visibility,
applicationTypes,
packageTypes,
packageBundlers,
monorepoTypes,
scope,
tests,
Expand All @@ -31,6 +32,7 @@ export default async function ({
visibility,
scope,
packageTypes,
packageBundlers,
tests,
vcs,
decisions,
Expand Down
Loading

0 comments on commit 46fb4ae

Please sign in to comment.