Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

work on composing projects out of npm packages/segments #53

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"[typescript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"typescript.tsdk": "node_modules/typescript/lib",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"scripts": {
"cli:styles": "lerna run build && ./packages/cli/bin/radius styles",
"cli:init": "lerna run build && ./packages/cli/bin/radius init",
"cli:create": "lerna run build && ./packages/cli/bin/radius create",
"build-all": "lerna run build",
"test-all": "lerna run test",
"lint-all": "lerna run lint",
Expand All @@ -19,7 +20,6 @@
}
},
"devDependencies": {
"@types/fs-extra": "^9.0.13",
"@types/inquirer": "^8.2.1",
"@types/jest": "^27.5.1",
"@types/node": "17.0.21",
Expand Down
130 changes: 130 additions & 0 deletions packages/cli/src/commands/create/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { mkdirp } from 'fs-extra';
import { spawn, SpawnOptionsWithoutStdio } from 'child_process';
import { CommandModule } from 'yargs';
import path from 'path';
import { logger } from '../../logger';

import * as inquirer from './utils/inquirer';

const spawnWithAPromise = (command: string, args: string[], options: SpawnOptionsWithoutStdio) => {

return new Promise((resolve) => {

console.log('spawning', JSON.stringify({ command, args, options }));

const ls = spawn(command, args, options );

ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});

ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
// reject(data);
});

ls.on('exit', function (code) {
console.log('child process exited with code ' + code);
resolve(code);
});

});

};

type Options = {};

export const create: CommandModule<Options, Options> = {
command: 'create',
describe: 'Create a DS starter (segment version)',

builder: (yargs) => {
return yargs;
},

handler: async () => {
logger.info(
'💿 Welcome to Radius with Segments! Let\'s get you set up with a new project.\n\r'
);
const designSystemOptions = await inquirer.askForDesignSystemOptions();
console.log('chosen options', designSystemOptions);


const dir = `packages/${ designSystemOptions['ds-name'] }`;

const packageListWithoutVersions = [designSystemOptions.starter, ...designSystemOptions.segments];

const packageList = packageListWithoutVersions
.map((packageName: string) => packageName + '@*');

console.log('project dir:', dir);
console.log('package list:', packageList);

// postinstall scripts can't assume the project is located at '../' since I'm working in a monorepo right now
// trailing '/' is included on the path to simplify code in packages, but it will get more complex eventually
process.env.radius_project_path = '/' + path.relative('/', `./${ dir }`) + '/';

console.log('radius project path:',process.env.radius_project_path);

console.info('making directory', dir);
await mkdirp(dir);
console.info('made directory', dir);

console.info('yarn init');
const initResult = await spawnWithAPromise('yarn', ['init', '--yes'], { cwd: dir });
console.info('yarn init result', initResult);

console.info('yarn install');
const installResult = await spawnWithAPromise(
'yarn',
['add', ...packageList, '--foreground-scripts'],
{ cwd: dir }
);
console.info('yarn install result', installResult);


if (packageListWithoutVersions.includes('radius-storybook')) {
await spawnWithAPromise('npx', ['storybook', 'init'], { cwd:dir });
}

}
};
/**
*
* @param packageListWithoutVersions

/*
* what if rather than node postinstall scripts we had our own system?
* I ran itno a surprising amout of path issues, but I don't think it is imppossible

const runPostInstallScripts = (packageListWithoutVersions: string[]) => {

console.log('looking for post install scripts');


for (let i = 0; i < packageListWithoutVersions.length; i++) {
const packageName = packageListWithoutVersions[i];

const segmentRelativePath = '../' + packageName;
const segmentAbsolutePath = path.resolve(process.env.radius_project_path, '../', packageName);

console.log({ segmentAbsolutePath, segmentRelativePath });

const postInstallScriptRelativeToSegment = 'postinstall.mjs';
const postinstallScriptAbsolutePath = segmentAbsolutePath + '/postinstall.mjs';

console.log('how about', postinstallScriptAbsolutePath, '?');
if (existsSync(postinstallScriptAbsolutePath)) {
console.log('running', postinstallScriptAbsolutePath );
await spawnWithAPromise(
'node',
[postInstallScriptRelativeToSegment],
{
cwd: segmentAbsolutePath
}
);
}
}

};
*/
1 change: 1 addition & 0 deletions packages/cli/src/commands/create/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './command';
32 changes: 32 additions & 0 deletions packages/cli/src/commands/create/utils/inquirer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { filter, isReact, validateDesignSystemNameAnswer } from './inquirer';

describe('Inquirer', () => {
it('should accept a design system name', () => {
const designSystemName = 'This is an awesome test';
expect(validateDesignSystemNameAnswer(designSystemName)).toBe(true);
});

it('should prompt the question again if design system name is empty or only white space', () => {
const designSystemNameEmpty = '';
const designSystemNameEmptySpace = ' ';
expect(validateDesignSystemNameAnswer(designSystemNameEmpty)).toBe(
'Please enter the name of the design system'
);
expect(validateDesignSystemNameAnswer(designSystemNameEmptySpace)).toBe(
'Please enter the name of the design system'
);
});

it('should make everything lower case', () => {
const val = 'I AM ALL CAPS, MAKE ME LOWER CASE';
expect(filter(val)).toBe('i am all caps, make me lower case');
});

it.skip('should check if the answer is react', () => {
expect(
isReact({
'ds-framework': 'react'
})
).toBeTruthy();
});
});
59 changes: 59 additions & 0 deletions packages/cli/src/commands/create/utils/inquirer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import inquirer, { QuestionCollection } from 'inquirer';

export const validateDesignSystemNameAnswer = (response: string) => {
if (response.trim().length) {
return true;
} else {
return 'Please enter the name of the design system';
}
};

export const filter = (val: string) => {
return val.toLowerCase();
};

export const isReact = (answers: any) => {
return answers['ds-framework'] === 'react';
};

export const askForDesignSystemOptions = () => {
return inquirer.prompt(questions);
};

const questions: QuestionCollection = [
{
name: 'ds-name',
type: 'input',
message: 'Enter the name of the design system:',
validate: validateDesignSystemNameAnswer
},
{
name: 'starter',
type: 'list',
choices: ['radius-react-vite'],
message: 'Which project do you want to use as a base?'
// filter
},
{
name: 'segments',
type: 'checkbox',
choices: ['test-segment-1', 'test-segment-2', 'radius-storybook'],
message: 'Which segments do you want to add?'
// filter
}
// {
// name: 'ds-framework',
// type: 'list',
// choices: ['angular', 'react', 'stencil'],
// message: 'Which framework you want to use?',
// filter
// },
// {
// name: 'ds-react-style',
// type: 'list',
// choices: ['css', 'styled-components', 'emotion'],
// message: 'How do you want to create components?',
// filter,
// when: isReact
// }
];
2 changes: 2 additions & 0 deletions packages/cli/src/radius.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CommandModule } from 'yargs';
import 'dotenv/config';

import { styles } from './commands/styles';
import { create } from './commands/create';
import { init } from './commands/init';

console.log(
Expand Down Expand Up @@ -40,6 +41,7 @@ module.exports = function radius(cwd: string) {
'A command is required. Pass --help to see all available commands and options.'
)
.command(init as CommandModule)
.command(create as CommandModule)
.command(styles as CommandModule);

return parser;
Expand Down
Loading