Plop - just-stack switched to using plop for codegen (#194)

* moving to plop

* plopped it good

* continue on the journey to plop

* WIP: getting monorepo plopped up

* monorepo test

* uifabric works!

* code gen subsequent packages

* Change files

* yarn.lock

* changed behavior of the downloadPackage function
This commit is contained in:
Kenneth Chau 2019-08-04 23:06:02 -07:00 коммит произвёл GitHub
Родитель 185663bd7a
Коммит 3f32788be4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
134 изменённых файлов: 1670 добавлений и 68798 удалений

1
.prettierignore Normal file
Просмотреть файл

@ -0,0 +1 @@
**/plop-templates/**

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "major",
"comment": "Switches to using plop.js for codegen",
"packageName": "create-just",
"email": "kchau@microsoft.com",
"commit": "2ea4e433c300ed8323aaab0fcf03f927ba8ab78b",
"date": "2019-08-05T05:37:37.993Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "minor",
"comment": "Getting rid of defunct just-stack / monorepo tasks",
"packageName": "just-scripts",
"email": "kchau@microsoft.com",
"commit": "2ea4e433c300ed8323aaab0fcf03f927ba8ab78b",
"date": "2019-08-05T05:38:12.241Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "Switches to using plop.js for codegen",
"packageName": "just-scripts-utils",
"email": "kchau@microsoft.com",
"commit": "2ea4e433c300ed8323aaab0fcf03f927ba8ab78b",
"date": "2019-08-05T05:37:52.360Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "minor",
"comment": "Switched to Lerna",
"packageName": "just-stack-monorepo",
"email": "kchau@microsoft.com",
"commit": "2ea4e433c300ed8323aaab0fcf03f927ba8ab78b",
"date": "2019-08-05T05:38:24.049Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "minor",
"comment": "code gen subsequent packages",
"packageName": "just-stack-react",
"email": "kchau@microsoft.com",
"commit": "2ea4e433c300ed8323aaab0fcf03f927ba8ab78b",
"date": "2019-08-05T05:38:31.984Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "minor",
"comment": "Switches to using plop.js for codegen",
"packageName": "just-stack-single-lib",
"email": "kchau@microsoft.com",
"commit": "2ea4e433c300ed8323aaab0fcf03f927ba8ab78b",
"date": "2019-08-05T05:38:36.357Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "minor",
"comment": "Switches to using plop.js for codegen",
"packageName": "just-stack-uifabric",
"email": "kchau@microsoft.com",
"commit": "2ea4e433c300ed8323aaab0fcf03f927ba8ab78b",
"date": "2019-08-05T05:38:39.894Z"
}

Просмотреть файл

@ -14,7 +14,7 @@
"change": "beachball change",
"checkchange": "beachball check",
"publish:beachball": "beachball publish",
"start": "node ./scripts/watch.js",
"start": "lerna run start --parallel",
"test": "lerna run test",
"lint": "eslint packages --ext .ts,.js"
},

Просмотреть файл

@ -12,22 +12,25 @@
},
"scripts": {
"build": "npx webpack",
"start": "npx webpack --watch --progress --display minimal --mode development"
"start": "npx webpack --watch --progress --display minimal --mode development",
"watch": "tsc -w --preserveWatchOutput"
},
"keywords": [],
"author": "",
"devDependencies": {
"@types/node": "^10.12.18",
"@types/prompts": "^1.2.0",
"@types/yargs": "12.0.1",
"@types/yargs-parser": "^13.0.0",
"@types/fs-extra": "^5.0.4",
"typescript": "~3.4.4",
"envinfo": "^7.3.1",
"typescript": "~3.5.3",
"fs-extra": "^7.0.1",
"prompts": "^2.0.1",
"yargs": "^12.0.5",
"yargs-parser": "^13.1.1",
"node-plop": "^0.19.0",
"webpack": "~4.29.5",
"webpack-cli": "^3.2.1",
"ts-loader": "^5.3.3",
"ts-loader": "^6.0.4",
"just-scripts-utils": ">=0.8.2 <1.0.0"
}
}

Просмотреть файл

@ -0,0 +1,13 @@
export function convertToBypass(gen: any, args: any) {
const prompts = gen.prompts;
const bypassArgs = args._;
prompts.forEach((prompt: any, index: number) => {
if (prompt.name && args[prompt.name] !== undefined) {
bypassArgs[index] = args[prompt.name];
}
});
return bypassArgs;
}

Просмотреть файл

@ -1,11 +1,11 @@
import { paths, logger, applyTemplate, prettyPrintMarkdown, rushUpdate, downloadPackage } from 'just-scripts-utils';
import { paths, logger, prettyPrintMarkdown, downloadPackage } from 'just-scripts-utils';
import path from 'path';
import { readdirSync } from 'fs';
import fse from 'fs-extra';
import { readdirSync, readFileSync, existsSync } from 'fs';
import prompts from 'prompts';
import { execSync, spawnSync } from 'child_process';
import { execSync } from 'child_process';
import yargs from 'yargs';
import os from 'os';
import { getPlopGenerator, runGenerator } from '../plop';
import * as pkg from '../packageManager';
const initCwd = process.cwd();
@ -13,19 +13,32 @@ function checkEmptyRepo(projectPath: string) {
return readdirSync(projectPath).length === 0;
}
async function getTemplatePath(pathName: string, registry?: string) {
function getStackName(stackPath: string) {
const packageJson = JSON.parse(readFileSync(path.join(stackPath, 'package.json'), 'utf-8'));
return packageJson.name;
}
async function getStackPath(pathName: string, registry?: string) {
if (pathName.match(/^\./)) {
// relative to initCwd
return path.join(initCwd, pathName, 'template');
} else if (pathName.match(/\//)) {
return path.join(initCwd, pathName);
} else if (pathName.match(/^\//)) {
// absolute path
return path.join(pathName, 'template');
return pathName;
}
// download it from feed
return await downloadPackage(pathName, undefined, registry);
}
/**
* Init involves these steps:
* 1. pick stack
* 2. pick name
* 3. plop!
* 4. git init and commit
* 5. yarn install
*/
export async function initCommand(argv: yargs.Arguments) {
// TODO: autosuggest just-stack-* packages from npmjs.org
if (!argv.stack) {
@ -34,9 +47,10 @@ export async function initCommand(argv: yargs.Arguments) {
name: 'stack',
message: 'What type of repo to create?',
choices: [
{ title: 'Monorepo', value: 'just-stack-monorepo' },
{ title: 'UI Fabric React Application', value: 'just-stack-uifabric' },
{ title: 'Basic library', value: 'just-stack-single-lib' }
{ title: 'React App', value: 'just-stack-react' },
{ title: 'UI Fabric (React)', value: 'just-stack-uifabric' },
{ title: 'Basic TypeScript', value: 'just-stack-single-lib' },
{ title: 'Monorepo', value: 'just-stack-monorepo' }
]
});
argv.stack = stack;
@ -48,7 +62,7 @@ export async function initCommand(argv: yargs.Arguments) {
type: 'text',
name: 'name',
message: 'What is the name of the repo to create?',
validate: (name) => !name ? false : true
validate: name => (!name ? false : true)
});
name = response.name;
paths.projectPath = path.join(paths.projectPath, name);
@ -59,50 +73,77 @@ export async function initCommand(argv: yargs.Arguments) {
paths.projectPath = path.join(paths.projectPath, name);
}
if (!fse.pathExistsSync(paths.projectPath)) {
fse.mkdirpSync(paths.projectPath);
}
argv.name = name;
process.chdir(paths.projectPath);
const stackPath = await getStackPath(argv.stack, argv.registry);
const stackName = getStackName(stackPath!);
const generator = getPlopGenerator(stackPath!, paths.projectPath, stackName);
logger.info(`Code Generation Information:
project path: ${paths.projectPath}
stack: ${stackName}
`);
await runGenerator(generator, argv);
logger.info(`Initializing the repo in ${paths.projectPath}`);
const templatePath = await getTemplatePath(argv.stack, argv.registry);
pkg.install(argv.registry, paths.projectPath);
if (templatePath) {
applyTemplate(templatePath, paths.projectPath, { name });
if (argv.stack.includes('monorepo')) {
rushUpdate(paths.projectPath);
} else {
const npmCmd = path.join(path.dirname(process.execPath), os.platform() === 'win32' ? 'npm.cmd' : 'npm');
spawnSync(npmCmd, ['install', ...(argv.registry ? ['--registry', argv.registry] : [])], { stdio: 'inherit' });
}
try {
execSync('git init');
execSync('git add .');
execSync('git commit -m "initial commit"');
} catch (e) {
logger.warn('Looks like you may not have git installed or there was some sort of error initializing the git repo');
logger.info(`
try {
execSync('git init', { cwd: paths.projectPath });
execSync('git add .', { cwd: paths.projectPath });
execSync('git commit -m "initial commit"', { cwd: paths.projectPath });
} catch (e) {
logger.warn('Looks like you may not have git installed or there was some sort of error initializing the git repo');
logger.info(`
Please make sure you have git installed and then issue the following:
cd ${paths.projectPath}
git init
git add .
git commit -m "initial commit"
cd ${paths.projectPath}
git init
git add .
git commit -m "initial commit"
`);
}
logger.info('All Set!');
const readmeFile = path.join(paths.projectPath, 'README.md');
if (fse.existsSync(readmeFile)) {
logger.info('\n' + prettyPrintMarkdown(fse.readFileSync(readmeFile).toString()));
}
} else {
logger.error('Having trouble downloading and extracting the template package');
}
logger.info('All Set!');
showNextSteps(argv, stackName);
}
function showNextSteps(argv: any, stackName: string) {
logger.info(
prettyPrintMarkdown(`
You have successfully created a new repo based on the '${argv.stack}' template!
## Keeping Up-to-date
You can keep your build tools up-to-date by updating these two devDependencies:
* ${stackName}
* just-scripts
## Next Steps
To start developing code, you can start the innerloop dev server:
cd ${paths.projectPath}
${pkg.getYarn() ? 'yarn' : 'npm'} start
You can build your project in production mode with these commands:
cd ${paths.projectPath}
${pkg.getYarn() ? 'yarn' : 'npm run'} build
${existsSync(path.join(paths.projectPath, 'plopfile.js')) &&
`
This repository contains code generators that can be triggered by:
cd ${paths.projectPath}
${pkg.getYarn() ? 'yarn' : 'npm run'} gen
`}`)
);
}

Просмотреть файл

@ -0,0 +1,32 @@
import envinfo from 'envinfo';
import os from 'os';
let envInfoCache: { Binaries: { Yarn: any; npm: any } };
export const getEnvInfo = () => {
return envInfoCache;
};
export const initialize = async () => {
envInfoCache = JSON.parse(
await envinfo.run(
{
Binaries: ['Yarn', 'npm']
},
{ json: true, showNotFound: true }
)
);
envInfoCache.Binaries.Yarn.path = envInfoCache.Binaries.Yarn && expandHome(envInfoCache.Binaries.Yarn.path);
envInfoCache.Binaries.npm.path = envInfoCache.Binaries.npm && expandHome(envInfoCache.Binaries.npm.path);
return envInfoCache;
};
function expandHome(path: string) {
if (path.startsWith('~/')) {
return path.replace('~/', os.homedir() + '/');
}
return path;
}

Просмотреть файл

@ -1,7 +1,25 @@
import yargs from 'yargs';
import parser from 'yargs-parser';
import { initCommand } from './commands/initCommand';
import { initialize } from './getEnvInfo';
yargs
const args = parser(process.argv.slice(2), {
alias: {
name: ['n'],
stack: ['s'],
registry: ['r']
}
});
if (args._.length > 0) {
args.name = args._[0];
}
(async () => {
await initialize();
initCommand(args);
})();
/*yargs
.command({
aliases: '*',
command: 'init [name]',
@ -13,3 +31,4 @@ yargs
handler: initCommand
})
.help().argv;
*/

Просмотреть файл

@ -0,0 +1,22 @@
import { spawnSync } from 'child_process';
import { getEnvInfo } from './getEnvInfo';
export function getYarn() {
const yarnInfo = getEnvInfo().Binaries.Yarn;
return yarnInfo && yarnInfo.path;
}
function getNpm() {
const npmInfo = getEnvInfo().Binaries.npm;
return npmInfo && npmInfo.path;
}
export function install(registry: string, cwd: string) {
const registryArgs = registry ? ['--registry', registry] : [];
if (getYarn()) {
return spawnSync(getYarn(), ['install', ...registryArgs], { stdio: 'inherit', cwd });
} else {
return spawnSync(getNpm(), ['install', ...registryArgs], { stdio: 'inherit', cwd });
}
}

Просмотреть файл

@ -0,0 +1,33 @@
import nodePlop from 'node-plop';
import path from 'path';
import { logger } from 'just-task-logger';
export function getPlopGenerator(plopfilePath: string, destBasePath: string, stackName: string) {
const plopfile = path.join(plopfilePath, 'plopfile.js');
const plop = nodePlop(plopfile, { destBasePath, force: false });
let generator = plop.getGenerator(`repo:${stackName}`) as any;
if (!generator) {
generator = plop.getGenerator('repo') as any;
}
return generator;
}
export async function runGenerator(generator: any, args: any) {
const results = await generator.runActions(args, {
onComment: (comment: string) => {
logger.info(comment);
}
});
if (results.failures && results.failures.length > 0) {
throw new Error('Error: ' + results.failures[0].error);
}
// do something after the actions have run
for (let change of results.changes) {
if (change.path) {
logger.info(change.path);
}
}
}

Просмотреть файл

@ -1,7 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib"
"outDir": "lib",
"noImplicitAny": false
},
"include": ["src/index.ts"]
}

4
packages/create-just/typings/envinfo.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
declare module 'envinfo' {
var x: any;
export = x;
}

Просмотреть файл

@ -23,5 +23,6 @@ module.exports = {
node: {
__dirname: false
},
devtool: 'none',
stats: 'errors-only'
};

Просмотреть файл

@ -66,10 +66,10 @@ describe('downloadPackage', () => {
expect(_isDevMode('foo')).toBe(false);
});
it('returns local template path in dev mode', async () => {
it('returns local path in dev mode', async () => {
const pkg = 'just-stack-monorepo';
const result = await downloadPackage(pkg);
expect(result).toBe(path.join(__dirname, '../../..', pkg, 'template'));
expect(result).toBe(path.join(__dirname, '../../..', pkg));
});
it('removes previous download and handles npm pack errors', async () => {
@ -120,6 +120,6 @@ describe('downloadPackage', () => {
});
const result = await downloadPackage(pkg, version);
expect(result).toBe(path.join(fakeTemp, pkg, 'package/template'));
expect(result).toBe(path.join(fakeTemp, pkg, 'package'));
});
});

Просмотреть файл

@ -37,7 +37,7 @@ export function _isDevMode(pkg: string): boolean {
*/
export async function downloadPackage(pkg: string, version: string = 'latest', registry: string | null = null): Promise<string | null> {
if (_isDevMode(pkg) && version === 'latest') {
return path.join(dirname || __dirname, '../../', pkg, 'template');
return path.join(dirname || __dirname, '../../', pkg);
}
const npmCmd = os.platform() === 'win32' ? 'npm.cmd' : 'npm';
@ -67,7 +67,7 @@ export async function downloadPackage(pkg: string, version: string = 'latest', r
file: path.join(pkgPath, pkgFile),
cwd: pkgPath
});
return path.join(pkgPath, 'package', 'template');
return path.join(pkgPath, 'package');
} else {
logger.error(`Could not find downloaded tgz file ${pkgPath}`);
return null;

Просмотреть файл

@ -1,3 +1,2 @@
export * from './lib';
export * from './monorepo';
export * from './webapp';

Просмотреть файл

@ -1,5 +1,5 @@
import { task, series, parallel } from 'just-task';
import { cleanTask, tscTask, jestTask, upgradeStackTask, defaultCleanPaths } from '../tasks';
import { cleanTask, tscTask, jestTask, defaultCleanPaths, tslintTask } from '../tasks';
export function lib() {
task('clean', cleanTask([...defaultCleanPaths(), 'lib-commonjs']));
@ -12,13 +12,14 @@ export function lib() {
task('jest', jestTask());
task('jest:watch', jestTask({ watch: true }));
task('build', series('clean', 'ts', 'jest'));
task('tslint', tslintTask());
task('build', series('ts'));
task('test', series('jest'));
task('lint', series('tslint'));
task('test', series('clean', 'jest'));
task('start', series('clean', 'ts:watch'));
task('start-test', series('clean', 'jest:watch'));
task('start-test', series('jest:watch'));
task('rebuild', series('clean', 'build'));
task('upgrade-stack', upgradeStackTask());
}

Просмотреть файл

@ -1,11 +0,0 @@
import { task, option } from 'just-task';
import { addPackageTask, upgradeRepoTask } from '../tasks';
export function monorepo() {
option('cwd');
option('name', { alias: 'n' });
option('stack', { alias: 's' });
option('latest');
task('add-package', 'adds a package to the monorepo', addPackageTask);
task('upgrade-repo', 'upgrades packages inside the monorepo according to the just-stack template', upgradeRepoTask);
}

Просмотреть файл

@ -1,27 +1,26 @@
import { task, series, parallel } from 'just-task';
import { cleanTask, tscTask, jestTask, webpackTask, webpackDevServerTask, upgradeStackTask, defaultCleanPaths } from '../tasks';
import { cleanTask, tscTask, jestTask, webpackTask, webpackDevServerTask, defaultCleanPaths, tslintTask } from '../tasks';
export function webapp() {
task('clean', cleanTask([...defaultCleanPaths(), 'lib-commonjs']));
task('ts:commonjs', tscTask({ module: 'commonjs', outDir: 'lib-commonjs' }));
task('ts:esm', tscTask({ module: 'esnext', outDir: 'lib' }));
task('ts:watch', tscTask({ module: 'esnext', outDir: 'lib', watch: true }));
task('ts', parallel('ts:commonjs', 'ts:esm'));
task('ts', parallel('ts:esm'));
task('jest', jestTask());
task('jest:watch', jestTask({ watch: true }));
task('tslint', tslintTask());
task('webpack', webpackTask());
task('webpack:watch', webpackDevServerTask());
task('build', series('clean', 'ts', parallel('jest', 'webpack')));
task('test', series('clean', 'jest'));
task('start', series('clean', 'webpack:watch'));
task('start-test', series('clean', 'jest:watch'));
task('build', series('ts', 'webpack'));
task('test', series('jest'));
task('start', series('webpack:watch'));
task('start-test', series('jest:watch'));
task('rebuild', series('clean', 'build'));
task('upgrade-stack', upgradeStackTask());
}

Просмотреть файл

@ -1,8 +1,8 @@
export const displayBailoutOverlay = {
export const displayBailoutOverlay = () => ({
stats: {
// Examine all modules
maxModules: Infinity,
// Display bailout reasons
optimizationBailout: true
}
};
});

Просмотреть файл

@ -1,4 +1,4 @@
export const fileOverlay = {
export const fileOverlay = () => ({
module: {
rules: [
{
@ -7,4 +7,7 @@ export const fileOverlay = {
}
]
}
};
});
// @deprecated - we used to give default options only, now we use functions as a convention
fileOverlay.module = fileOverlay().module;

Просмотреть файл

@ -2,6 +2,6 @@ import { tryRequire } from '../../tryRequire';
const HtmlWebpackPlugin = tryRequire('html-webpack-plugin');
export const htmlOverlay = {
plugins: [...(HtmlWebpackPlugin ? [new HtmlWebpackPlugin()] : [])]
};
export const htmlOverlay = (options: any) => ({
plugins: [...(HtmlWebpackPlugin ? [new HtmlWebpackPlugin(options)] : [])]
});

Просмотреть файл

@ -107,6 +107,7 @@ export const createStylesOverlay = function(options: CssLoaderOptions = {}) {
};
};
export const stylesOverlay = createStylesOverlay({
localIdentName: defaultIdentName
});
export const stylesOverlay = () =>
createStylesOverlay({
localIdentName: defaultIdentName
});

Просмотреть файл

@ -2,7 +2,7 @@ import { tryRequire } from '../../tryRequire';
const ForkTsCheckerPlugin = tryRequire('fork-ts-checker-webpack-plugin');
export const tsOverlay = {
export const tsOverlay = () => ({
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.ts', '.tsx', '.json']
},
@ -21,4 +21,4 @@ export const tsOverlay = {
]
},
plugins: [...(ForkTsCheckerPlugin ? [new ForkTsCheckerPlugin()] : [])]
};
});

Просмотреть файл

@ -14,4 +14,4 @@ export const basicWebpackConfig: any = {
}
};
export const webpackConfig: any = merge(basicWebpackConfig, stylesOverlay, tsOverlay, fileOverlay, displayBailoutOverlay);
export const webpackConfig: any = merge(basicWebpackConfig, stylesOverlay(), tsOverlay(), fileOverlay(), displayBailoutOverlay());

Просмотреть файл

@ -14,4 +14,4 @@ export const basicWebpackServeConfig: any = {
}
};
export const webpackServeConfig: any = merge(basicWebpackServeConfig, stylesOverlay, tsOverlay, fileOverlay);
export const webpackServeConfig: any = merge(basicWebpackServeConfig, stylesOverlay(), tsOverlay(), fileOverlay());

Просмотреть файл

@ -1,5 +1,3 @@
CHANGELOG.*
*.log
package-deps.json
template.spec.js
jest.config.js
ndoe_modules

Просмотреть файл

@ -1 +0,0 @@
module.exports = require('../../scripts/jest.template.config');

Просмотреть файл

@ -12,17 +12,5 @@
"just-stack"
],
"author": "",
"license": "MIT",
"scripts": {
"build": "npm test",
"test": "jest"
},
"devDependencies": {
"fs-extra": "^7.0.1",
"glob": "^7.1.3",
"jest": "^24.0.0",
"jest-expect-message": "^1.0.2",
"json5": "^2.1.0",
"just-scripts-utils": "0.8.2"
}
"license": "MIT"
}

Просмотреть файл

@ -0,0 +1,3 @@
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-typescript', '@babel/preset-react']
};

Просмотреть файл

@ -0,0 +1,4 @@
node_modules
lib
lib-commonjs
dist

Просмотреть файл

@ -0,0 +1,5 @@
module.exports = {
clearMocks: true,
testEnvironment: 'jsdom',
testMatch: ['<rootDir>/src/**/__tests__/**/*.[jt]s?(x)', '<rootDir>/src/**/?(*.)+(spec|test).[tj]s?(x)']
};

Просмотреть файл

@ -1,3 +1,3 @@
// @ts-check
const { taskPresets } = require('just-scripts');
taskPresets.webapp();

Просмотреть файл

@ -0,0 +1,23 @@
{
"name": "{{name}}",
"version": "0.1.0",
"license": "MIT",
"main": "lib-commonjs/index.js",
"module": "lib/index.js",
"scripts": {
"build": "just-scripts build",
"just": "just-scripts",
"start": "just-scripts start",
"test": "just-scripts test",
"change": "npx beachball change",
"gen": "npx plop"
},
"dependencies": {
"react": "^16.8.6",
"react-dom": "^16.8.6"
},
"devDependencies": {
"just-stack-react": "^0.2.0",
"{{repoName}}-scripts": "^0.26.0"
}
}

Просмотреть файл

@ -0,0 +1,13 @@
import React from 'react';
export interface \{{pascalCase componentName}}Props {
// Fill in props here
}
export const \{{pascalCase componentName}} = (props: \{{pascalCase componentName}}Props) => {
return (
<div>
{/* TODO */}
</div>
);
}

Просмотреть файл

@ -0,0 +1,19 @@
module.exports = plop => {
plop.setGenerator('component', {
prompts: [
{
type: 'input',
name: 'componentName',
message: 'Name of the component (will be converted to PascalCase): '
}
],
actions: [
{
type: 'add',
templateFile: 'plop-templates/component/component.tsx.hbs',
path: 'src/components/{{pascalCase componentName}}.tsx'
}
]
});
};

Просмотреть файл

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<div id="app"/>
</body>
</html>

Просмотреть файл

@ -0,0 +1,3 @@
import React from 'react';
export default () => <div>This is an application</div>;

Просмотреть файл

@ -0,0 +1,7 @@
import { hello } from '../helloworld';
describe('hello', () => {
it('says hello', () => {
const result = hello('world');
expect(result).toBe('hello world');
});
});

Просмотреть файл

@ -0,0 +1,3 @@
export const hello = (name: string) => {
return `hello ${name}`;
};

Просмотреть файл

@ -0,0 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('app'));

Просмотреть файл

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"jsx": "react",
"declaration": true,
"outDir": "./lib",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"typeRoots": ["node_modules/@types", "node_modules/just-stack-react/node_modules/@types"]
},
"include": ["src", "typings/*.d.ts"]
}

Просмотреть файл

@ -0,0 +1,11 @@
const { webpackConfig, webpackMerge, htmlOverlay } = require('just-scripts');
module.exports = webpackMerge(
webpackConfig,
htmlOverlay({
template: 'public/index.html'
}),
{
// Here you can custom webpack configurations
}
);

Просмотреть файл

@ -0,0 +1,13 @@
const { webpackMerge, htmlOverlay, webpackServeConfig } = require('just-scripts');
module.exports = webpackMerge(
webpackServeConfig,
htmlOverlay({
template: 'public/index.html'
}),
{
// Here you can custom webpack configurations
output: {
publicPath: '/'
}
}
);

4
packages/just-stack-monorepo/plop-templates/repo/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
node_modules
lib
lib-commonjs
dist

Просмотреть файл

@ -0,0 +1,6 @@
{
"packages": ["packages/*", "scripts"],
"useWorkspaces": true,
"npmClient": "yarn",
"version": "0.0.0"
}

Просмотреть файл

@ -0,0 +1,20 @@
{
"name": "{{name}}",
"private": true,
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"workspaces": ["packages/*", "scripts"],
"devDependencies": {
"just-stack-monorepo": "^0.6.2",
"lerna": "^3.13.2",
"beachball": "^1.11.5",
"plop": "^2.4.0"
},
"scripts": {
"build": "lerna run build --stream",
"test": "lerna run test --stream",
"change": "beachball change",
"gen": "plop"
}
}

Просмотреть файл

@ -0,0 +1,3 @@
module.exports = function(plop) {
plop.load('just-stack-monorepo/plopfile.repo.js');
};

Просмотреть файл

@ -0,0 +1,2 @@
#!/usr/bin/env node
require('just-scripts/bin/just-scripts');

Просмотреть файл

@ -0,0 +1,15 @@
{
"name": "{{name}}-scripts",
"private": true,
"version": "0.0.1",
"description": "",
"main": "index.js",
"author": "",
"license": "MIT",
"bin": {
"{{name}}-scripts": "just-scripts.js"
},
"dependencies": {
"just-scripts": "^0.26.0"
}
}

Просмотреть файл

@ -0,0 +1,13 @@
module.exports = function(plop) {
plop.setGenerator('repo:just-stack-monorepo', {
actions: [
{
type: 'addMany',
templateFiles: ['plop-templates/**/*.*', 'plop-templates/**/.*'],
base: 'plop-templates/repo',
destination: '.',
force: true
}
]
});
};

Просмотреть файл

@ -0,0 +1,27 @@
const fs = require('fs');
module.exports = function(plop) {
const packageJson = JSON.parse(fs.readFileSync(require.resolve('package.json', { paths: [process.cwd()] })));
plop.setGenerator('react-package', {
description: `Generates a React package`,
prompts: [
{
type: 'input',
name: 'name',
message: 'Enter a name for the package: '
}
],
actions: [
{
type: 'addMany',
templateFiles: ['plop-templates/react-package/**/*', 'plop-templates/react-package/**/.*'],
destination: 'packages/{{name}}',
base: 'plop-templates/react-package',
data: {
repoName: packageJson.name
}
}
]
});
};

Просмотреть файл

@ -1,36 +0,0 @@
const path = require('path');
const fse = require('fs-extra');
const glob = require('glob');
const json = require('json5');
const { applyTemplate } = require('just-scripts-utils');
describe('stack snapshot', () => {
const snapshotPath = path.resolve(__dirname, 'temp');
const templatePath = path.resolve(__dirname, 'template');
let jsonFiles;
afterAll(() => {
fse.removeSync(snapshotPath);
});
beforeAll(() => {
applyTemplate(templatePath, snapshotPath, { name: 'testproject' });
jsonFiles = glob.sync('**/*.json', { cwd: snapshotPath });
});
it('has legal json files', () => {
jsonFiles.forEach(jsonFile => {
if (jsonFile.includes('rush')) {
expect(
() => json.parse(fse.readFileSync(path.resolve(snapshotPath, jsonFile)).toString()),
`${jsonFile} cannot be parsed as JSON (with comments).`
).not.toThrow();
} else {
expect(
() => JSON.parse(fse.readFileSync(path.resolve(snapshotPath, jsonFile)).toString()),
`${jsonFile} cannot be parsed as JSON.`
).not.toThrow();
}
});
});
});

Просмотреть файл

@ -1,31 +0,0 @@
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.DS_Store
node_modules
lib
lib-commonjs
lib-esm
lib-es2015
build
coverage
dist
temp
*.scss.ts
documentation/lib/core/metadata.js
documentation/lib/core/MetadataBlog.js
documentation/website/translated_docs
documentation/website/build/
documentation/website/yarn.lock
documentation/website/i18n/*
# Rush files
common/temp/**
package-deps.json

Просмотреть файл

@ -1,26 +0,0 @@
{
// When enabled, will trim trailing whitespace when you save a file.
"files.trimTrailingWhitespace": true,
// Controls whether the editor should render whitespace characters
"editor.renderWhitespace": "all",
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/coverage": true,
"**/*.scss.ts": true
},
// Configure glob patterns for excluding files and folders in searches. Inherits all glob patterns from the file.exclude setting.
"search.exclude": {
"common/temp": true,
"**/node_modules": true,
"**/lib": true,
"**/lib-commonjs": true,
"**/lib-esm": true,
"**/lib-es2015": true,
"**/dist": true
},
"files.associations": {
"rush.json": "jsonc",
"**/common/config/rush/*.json": "jsonc"
}
}

Просмотреть файл

@ -1,12 +0,0 @@
# {{name}}
{{name}} is a monorepo created and managed with the `create-just` utility.
## Next Steps
Now that you have created this repository, run the following to get started:
```sh
npm install
npm run add-package
```

Просмотреть файл

@ -1,177 +0,0 @@
/**
* This configuration file defines custom commands for the "rush" command-line.
* For full documentation, please see https://rushjs.io
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json",
/**
* Custom "commands" introduce new verbs for the command-line. To see the help for these
* example commands, try "rush --help", "rush my-bulk-command --help", or
* "rush my-global-command --help".
*/
"commands": [
// {
// /**
// * (Required) Determines the type of custom command.
// * Rush's "bulk" commands are invoked separately for each project. Rush will look in
// * each project's package.json file for a "scripts" entry whose name matches the
// * command name. By default, the command will run for every project in the repo,
// * according to the dependency graph (similar to how "rush build" works).
// * The set of projects can be restricted e.g. using the "--to" or "--from" parameters.
// */
// "commandKind": "bulk",
// /**
// * (Required) The name that will be typed as part of the command line. This is also the name
// * of the "scripts" hook in the project's package.json file.
// * The name should be comprised of lower case words separated by hyphens.
// */
// "name": "my-bulk-command",
// /**
// * (Required) A short summary of the custom command to be shown when printing command line
// * help, e.g. "rush --help".
// */
// "summary": "Example bulk custom command",
// /**
// * A detailed description of the command to be shown when printing command line
// * help (e.g. "rush --help my-command").
// * If omitted, the "summary" text will be shown instead.
// *
// * Whenever you introduce commands/parameters, taking a little time to write meaningful
// * documentation can make a big difference for the developer experience in your repo.
// */
// "description": "This is an example custom command that runs separately for each project",
// /**
// * (Required) If true, then this command is safe to be run in parallel, i.e. executed
// * simultaneously for multiple projects. Similar to "rush build", regardless of parallelism
// * projects will not start processing until their dependencies have completed processing.
// */
// "enableParallelism": false,
// /**
// * Normally Rush requires that each project's package.json has a "scripts" entry matching
// * the custom command name. To disable this check, set "ignoreMissingScript" to true;
// * projects with a missing definition will be skipped.
// */
// "ignoreMissingScript": false
// },
// {
// /**
// * (Required) Determines the type of custom command.
// * Rush's "global" commands are invoked once for the entire repo.
// */
// "commandKind": "global",
// "name": "my-global-command",
// "summary": "Example global custom command",
// "description": "This is an example custom command that runs once for the entire repo",
// /**
// * A script that will be invoked using the OS shell. The working directory will be the folder
// * that contains rush.json. If custom parameters are associated with this command, their
// * values will be appended to the end of this string.
// */
// "shellCommand": "node common/scripts/my-global-command.js"
// }
],
/**
* Custom "parameters" introduce new parameters for specified Rush command-line commands.
* For example, you might define a "--production" parameter for the "rush build" command.
*/
"parameters": [
// {
// /**
// * (Required) Determines the type of custom parameter.
// * A "flag" is a custom command-line parameter whose presence acts as an on/off switch.
// */
// "parameterKind": "flag",
// /**
// * (Required) The long name of the parameter. It must be lower-case and use dash delimiters.
// */
// "longName": "--my-flag",
// /**
// * An optional alternative short name for the parameter. It must be a dash followed by a single
// * lower-case or upper-case letter, which is case-sensitive.
// *
// * NOTE: The Rush developers recommend that automation scripts should always use the long name
// * to improve readability. The short name is only intended as a convenience for humans.
// * The alphabet letters run out quickly, and are difficult to memorize, so *only* use
// * a short name if you expect the parameter to be needed very often in everyday operations.
// */
// "shortName": "-m",
// /**
// * (Required) A long description to be shown in the command-line help.
// *
// * Whenever you introduce commands/parameters, taking a little time to write meaningful
// * documentation can make a big difference for the developer experience in your repo.
// */
// "description": "A custom flag parameter that is passed to the scripts that are invoked when building projects",
// /**
// * (Required) A list of custom commands and/or built-in Rush commands that this parameter may
// * be used with. The parameter will be appended to the shell command that Rush invokes.
// */
// "associatedCommands": [ "build", "rebuild" ]
// },
// {
// /**
// * (Required) Determines the type of custom parameter.
// * A "flag" is a custom command-line parameter whose presence acts as an on/off switch.
// */
// "parameterKind": "choice",
// "longName": "--my-choice",
// "description": "A custom choice parameter for the \"my-global-command\" custom command",
// "associatedCommands": [ "my-global-command" ],
// /**
// * Normally if a parameter is omitted from the command line, it will not be passed
// * to the shell command. this value will be inserted by default. Whereas if a "defaultValue"
// * is defined, the parameter will always be passed to the shell command, and will use the
// * default value if unspecified. The value must be one of the defined alternatives.
// */
// "defaultValue": "vanilla",
// /**
// * (Required) A list of alternative argument values that can be chosen for this parameter.
// */
// "alternatives": [
// {
// /**
// * A token that is one of the alternatives that can be used with the choice parameter,
// * e.g. "vanilla" in "--flavor vanilla".
// */
// "name": "vanilla",
// /**
// * A detailed description for the alternative that can be shown in the command-line help.
// *
// * Whenever you introduce commands/parameters, taking a little time to write meaningful
// * documentation can make a big difference for the developer experience in your repo.
// */
// "description": "Use the vanilla flavor (the default)"
// },
// {
// "name": "chocolate",
// "description": "Use the chocolate flavor"
// },
// {
// "name": "strawberry",
// "description": "Use the strawberry flavor"
// }
// ]
// }
]
}

Просмотреть файл

@ -1,43 +0,0 @@
/**
* This configuration file specifies NPM dependency version selections that affect all projects
* in a Rush repo. For full documentation, please see https://rushjs.io
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json",
/**
* A table that specifies a "preferred version" for a dependency package. The "preferred version"
* is typically used to hold an indirect dependency back to a specific version, however generally
* it can be any SemVer range specifier (e.g. "~1.2.3"), and it will narrow any (compatible)
* SemVer range specifier. See the Rush documentation for details about this feature.
*/
"preferredVersions": {
/**
* When someone asks for "^1.0.0" make sure they get "1.2.3" when working in this repo,
* instead of the latest version.
*/
// "some-library": "1.2.3"
},
/**
* The "rush check" command can be used to enforce that every project in the repo must specify
* the same SemVer range for a given dependency. However, sometimes exceptions are needed.
* The allowedAlternativeVersions table allows you to list other SemVer ranges that will be
* accepted by "rush check" for a given dependency.
*
* IMPORTANT: THIS TABLE IS FOR *ADDITIONAL* VERSION RANGES THAT ARE ALTERNATIVES TO THE
* USUAL VERSION (WHICH IS INFERRED BY LOOKING AT ALL PROJECTS IN THE REPO).
* This design avoids unnecessary churn in this file.
*/
"allowedAlternativeVersions": {
/**
* For example, allow some projects to use an older TypeScript compiler
* (in addition to whatever "usual" version is being used by other projects in the repo):
*/
// "typescript": [
// "~2.4.0"
// ]
}
}

Просмотреть файл

@ -1,34 +0,0 @@
/**
* This is configuration file is used for advanced publishing configurations with Rush.
* For full documentation, please see https://rushjs.io
*/
/**
* A list of version policy definitions. A "version policy" is a custom package versioning
* strategy that affets "rush change", "rush version", and "rush publish". The strategy applies
* to a set of projects that are specified using the "versionPolicyName" field in rush.json.
*/
[
// {
// /**
// * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion").
// *
// * The "individualVersion" mode specifies that the projects will use "individual versioning".
// * This is the typical NPM model where each package has an independent version number
// * and CHANGELOG.md file. Although a single CI definition is responsible for publishing the
// * packages, they otherwise don't have any special relationship. The version bumping will
// * depend on how developers answer the "rush change" questions for each package that
// * is changed.
// */
// "definitionName": "individualVersion",
// "policyName": "RepoPolicy",
// /**
// * (Optional) This can be used to enforce that all packages in the set must share a common
// * major version number, e.g. because they are from the same major release branch.
// * It can also be used to discourage people from accidentally making "MAJOR" SemVer changes
// * inappropriately. The minor/patch version parts will be bumped independently according
// * to the types of changes made to each project, according to the "rush change" command.
// */
// "lockedMajor": 0
// }
]

Просмотреть файл

@ -1,52 +0,0 @@
"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See the @microsoft/rush package's LICENSE file for license information.
Object.defineProperty(exports, "__esModule", { value: true });
// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
//
// This script is intended for usage in an automated build environment where the Rush command may not have
// been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush
// specified in the rush.json configuration file (if not already installed), and then pass a command-line to it.
// An example usage would be:
//
// node common/scripts/install-run-rush.js install
//
// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
const path = require("path");
const fs = require("fs");
const install_run_1 = require("./install-run");
const PACKAGE_NAME = '@microsoft/rush';
function getRushVersion() {
const rushJsonFolder = install_run_1.findRushJsonFolder();
const rushJsonPath = path.join(rushJsonFolder, install_run_1.RUSH_JSON_FILENAME);
try {
const rushJsonContents = fs.readFileSync(rushJsonPath, 'utf-8');
// Use a regular expression to parse out the rushVersion value because rush.json supports comments,
// but JSON.parse does not and we don't want to pull in more dependencies than we need to in this script.
const rushJsonMatches = rushJsonContents.match(/\"rushVersion\"\s*\:\s*\"([0-9a-zA-Z.+\-]+)\"/);
return rushJsonMatches[1];
}
catch (e) {
throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` +
'The \'rushVersion\' field is either not assigned in rush.json or was specified ' +
'using an unexpected syntax.');
}
}
function run() {
const [nodePath, /* Ex: /bin/node */ scriptPath, /* /repo/common/scripts/install-run-rush.js */ ...packageBinArgs /* [build, --to, myproject] */] = process.argv;
if (!nodePath || !scriptPath) {
throw new Error('Unexpected exception: could not detect node path or script path');
}
if (process.argv.length < 3) {
console.log('Usage: install-run-rush.js <command> [args...]');
console.log('Example: install-run-rush.js build --to myproject');
process.exit(1);
}
install_run_1.runWithErrorAndStatusCode(() => {
const version = getRushVersion();
console.log(`The rush.json configuration requests Rush version ${version}`);
return install_run_1.installAndRun(PACKAGE_NAME, version, 'rush', packageBinArgs);
});
}
run();
//# sourceMappingURL=install-run-rush.js.map

Просмотреть файл

@ -1,399 +0,0 @@
"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See the @microsoft/rush package's LICENSE file for license information.
Object.defineProperty(exports, "__esModule", { value: true });
// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
//
// This script is intended for usage in an automated build environment where a Node tool may not have
// been preinstalled, or may have an unpredictable version. This script will automatically install the specified
// version of the specified tool (if not already installed), and then pass a command-line to it.
// An example usage would be:
//
// node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io
//
// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
const childProcess = require("child_process");
const fs = require("fs");
const os = require("os");
const path = require("path");
exports.RUSH_JSON_FILENAME = 'rush.json';
const INSTALLED_FLAG_FILENAME = 'installed.flag';
const NODE_MODULES_FOLDER_NAME = 'node_modules';
const PACKAGE_JSON_FILENAME = 'package.json';
/**
* Parse a package specifier (in the form of name\@version) into name and version parts.
*/
function parsePackageSpecifier(rawPackageSpecifier) {
rawPackageSpecifier = (rawPackageSpecifier || '').trim();
const separatorIndex = rawPackageSpecifier.lastIndexOf('@');
let name;
let version = undefined;
if (separatorIndex === 0) {
// The specifier starts with a scope and doesn't have a version specified
name = rawPackageSpecifier;
}
else if (separatorIndex === -1) {
// The specifier doesn't have a version
name = rawPackageSpecifier;
}
else {
name = rawPackageSpecifier.substring(0, separatorIndex);
version = rawPackageSpecifier.substring(separatorIndex + 1);
}
if (!name) {
throw new Error(`Invalid package specifier: ${rawPackageSpecifier}`);
}
return { name, version };
}
/**
* Resolve a package specifier to a static version
*/
function resolvePackageVersion(rushCommonFolder, { name, version }) {
if (!version) {
version = '*'; // If no version is specified, use the latest version
}
if (version.match(/^[a-zA-Z0-9\-\+\.]+$/)) {
// If the version contains only characters that we recognize to be used in static version specifiers,
// pass the version through
return version;
}
else {
// version resolves to
try {
const rushTempFolder = ensureAndJoinPath(rushCommonFolder, 'temp');
const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush');
syncNpmrc(sourceNpmrcFolder, rushTempFolder);
const npmPath = getNpmPath();
// This returns something that looks like:
// @microsoft/rush@3.0.0 '3.0.0'
// @microsoft/rush@3.0.1 '3.0.1'
// ...
// @microsoft/rush@3.0.20 '3.0.20'
// <blank line>
const npmVersionSpawnResult = childProcess.spawnSync(npmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier'], {
cwd: rushTempFolder,
stdio: []
});
if (npmVersionSpawnResult.status !== 0) {
throw new Error(`"npm view" returned error code ${npmVersionSpawnResult.status}`);
}
const npmViewVersionOutput = npmVersionSpawnResult.stdout.toString();
const versionLines = npmViewVersionOutput.split('\n').filter((line) => !!line);
const latestVersion = versionLines[versionLines.length - 1];
if (!latestVersion) {
throw new Error('No versions found for the specified version range.');
}
const versionMatches = latestVersion.match(/^.+\s\'(.+)\'$/);
if (!versionMatches) {
throw new Error(`Invalid npm output ${latestVersion}`);
}
return versionMatches[1];
}
catch (e) {
throw new Error(`Unable to resolve version ${version} of package ${name}: ${e}`);
}
}
}
let _npmPath = undefined;
/**
* Get the absolute path to the npm executable
*/
function getNpmPath() {
if (!_npmPath) {
try {
if (os.platform() === 'win32') {
// We're on Windows
const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString();
const lines = whereOutput.split(os.EOL).filter((line) => !!line);
// take the last result, we are looking for a .cmd command
// see https://github.com/Microsoft/web-build-tools/issues/759
_npmPath = lines[lines.length - 1];
}
else {
// We aren't on Windows - assume we're on *NIX or Darwin
_npmPath = childProcess.execSync('which npm', { stdio: [] }).toString();
}
}
catch (e) {
throw new Error(`Unable to determine the path to the NPM tool: ${e}`);
}
_npmPath = _npmPath.trim();
if (!fs.existsSync(_npmPath)) {
throw new Error('The NPM executable does not exist');
}
}
return _npmPath;
}
exports.getNpmPath = getNpmPath;
let _rushJsonFolder;
/**
* Find the absolute path to the folder containing rush.json
*/
function findRushJsonFolder() {
if (!_rushJsonFolder) {
let basePath = __dirname;
let tempPath = __dirname;
do {
const testRushJsonPath = path.join(basePath, exports.RUSH_JSON_FILENAME);
if (fs.existsSync(testRushJsonPath)) {
_rushJsonFolder = basePath;
break;
}
else {
basePath = tempPath;
}
} while (basePath !== (tempPath = path.dirname(basePath))); // Exit the loop when we hit the disk root
if (!_rushJsonFolder) {
throw new Error('Unable to find rush.json.');
}
}
return _rushJsonFolder;
}
exports.findRushJsonFolder = findRushJsonFolder;
/**
* Create missing directories under the specified base directory, and return the resolved directory.
*
* Does not support "." or ".." path segments.
* Assumes the baseFolder exists.
*/
function ensureAndJoinPath(baseFolder, ...pathSegments) {
let joinedPath = baseFolder;
try {
for (let pathSegment of pathSegments) {
pathSegment = pathSegment.replace(/[\\\/]/g, '+');
joinedPath = path.join(joinedPath, pathSegment);
if (!fs.existsSync(joinedPath)) {
fs.mkdirSync(joinedPath);
}
}
}
catch (e) {
throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`);
}
return joinedPath;
}
/**
* As a workaround, _syncNpmrc() copies the .npmrc file to the target folder, and also trims
* unusable lines from the .npmrc file. If the source .npmrc file not exist, then _syncNpmrc()
* will delete an .npmrc that is found in the target folder.
*
* Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in
* the .npmrc file to provide different authentication tokens for different registry.
* However, if the environment variable is undefined, it expands to an empty string, which
* produces a valid-looking mapping with an invalid URL that causes an error. Instead,
* we'd prefer to skip that line and continue looking in other places such as the user's
* home directory.
*
* IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc()
*/
function syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder) {
const sourceNpmrcPath = path.join(sourceNpmrcFolder, '.npmrc');
const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc');
try {
if (fs.existsSync(sourceNpmrcPath)) {
let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n');
npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim());
const resultLines = [];
// Trim out lines that reference environment variables that aren't defined
for (const line of npmrcFileLines) {
// This finds environment variable tokens that look like "${VAR_NAME}"
const regex = /\$\{([^\}]+)\}/g;
const environmentVariables = line.match(regex);
let lineShouldBeTrimmed = false;
if (environmentVariables) {
for (const token of environmentVariables) {
// Remove the leading "${" and the trailing "}" from the token
const environmentVariableName = token.substring(2, token.length - 1);
if (!process.env[environmentVariableName]) {
lineShouldBeTrimmed = true;
break;
}
}
}
if (lineShouldBeTrimmed) {
// Example output:
// "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}"
resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line);
}
else {
resultLines.push(line);
}
}
fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL));
}
else if (fs.existsSync(targetNpmrcPath)) {
// If the source .npmrc doesn't exist and there is one in the target, delete the one in the target
fs.unlinkSync(targetNpmrcPath);
}
}
catch (e) {
throw new Error(`Error syncing .npmrc file: ${e}`);
}
}
/**
* Detects if the package in the specified directory is installed
*/
function isPackageAlreadyInstalled(packageInstallFolder) {
try {
const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME);
if (!fs.existsSync(flagFilePath)) {
return false;
}
const fileContents = fs.readFileSync(flagFilePath).toString();
return fileContents.trim() === process.version;
}
catch (e) {
return false;
}
}
/**
* Removes the following files and directories under the specified folder path:
* - installed.flag
* -
* - node_modules
*/
function cleanInstallFolder(rushCommonFolder, packageInstallFolder) {
try {
const flagFile = path.resolve(packageInstallFolder, INSTALLED_FLAG_FILENAME);
if (fs.existsSync(flagFile)) {
fs.unlinkSync(flagFile);
}
const packageLockFile = path.resolve(packageInstallFolder, 'package-lock.json');
if (fs.existsSync(packageLockFile)) {
fs.unlinkSync(packageLockFile);
}
const nodeModulesFolder = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME);
if (fs.existsSync(nodeModulesFolder)) {
const rushRecyclerFolder = ensureAndJoinPath(rushCommonFolder, 'temp', 'rush-recycler', `install-run-${Date.now().toString()}`);
fs.renameSync(nodeModulesFolder, rushRecyclerFolder);
}
}
catch (e) {
throw new Error(`Error cleaning the package install folder (${packageInstallFolder}): ${e}`);
}
}
function createPackageJson(packageInstallFolder, name, version) {
try {
const packageJsonContents = {
'name': 'ci-rush',
'version': '0.0.0',
'dependencies': {
[name]: version
},
'description': 'DON\'T WARN',
'repository': 'DON\'T WARN',
'license': 'MIT'
};
const packageJsonPath = path.join(packageInstallFolder, PACKAGE_JSON_FILENAME);
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2));
}
catch (e) {
throw new Error(`Unable to create package.json: ${e}`);
}
}
/**
* Run "npm install" in the package install folder.
*/
function installPackage(packageInstallFolder, name, version) {
try {
console.log(`Installing ${name}...`);
const npmPath = getNpmPath();
const result = childProcess.spawnSync(npmPath, ['install'], {
stdio: 'inherit',
cwd: packageInstallFolder,
env: process.env
});
if (result.status !== 0) {
throw new Error('"npm install" encountered an error');
}
console.log(`Successfully installed ${name}@${version}`);
}
catch (e) {
throw new Error(`Unable to install package: ${e}`);
}
}
/**
* Get the ".bin" path for the package.
*/
function getBinPath(packageInstallFolder, binName) {
const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin');
const resolvedBinName = (os.platform() === 'win32') ? `${binName}.cmd` : binName;
return path.resolve(binFolderPath, resolvedBinName);
}
/**
* Write a flag file to the package's install directory, signifying that the install was successful.
*/
function writeFlagFile(packageInstallFolder) {
try {
const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME);
fs.writeFileSync(flagFilePath, process.version);
}
catch (e) {
throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`);
}
}
function installAndRun(packageName, packageVersion, packageBinName, packageBinArgs) {
const rushJsonFolder = findRushJsonFolder();
const rushCommonFolder = path.join(rushJsonFolder, 'common');
const packageInstallFolder = ensureAndJoinPath(rushCommonFolder, 'temp', 'install-run', `${packageName}@${packageVersion}`);
if (!isPackageAlreadyInstalled(packageInstallFolder)) {
// The package isn't already installed
cleanInstallFolder(rushCommonFolder, packageInstallFolder);
const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush');
syncNpmrc(sourceNpmrcFolder, packageInstallFolder);
createPackageJson(packageInstallFolder, packageName, packageVersion);
installPackage(packageInstallFolder, packageName, packageVersion);
writeFlagFile(packageInstallFolder);
}
const statusMessage = `Invoking "${packageBinName} ${packageBinArgs.join(' ')}"`;
const statusMessageLine = new Array(statusMessage.length + 1).join('-');
console.log(os.EOL + statusMessage + os.EOL + statusMessageLine + os.EOL);
const binPath = getBinPath(packageInstallFolder, packageBinName);
const result = childProcess.spawnSync(binPath, packageBinArgs, {
stdio: 'inherit',
cwd: process.cwd(),
env: process.env
});
return result.status;
}
exports.installAndRun = installAndRun;
function runWithErrorAndStatusCode(fn) {
process.exitCode = 1;
try {
const exitCode = fn();
process.exitCode = exitCode;
}
catch (e) {
console.error(os.EOL + os.EOL + e.toString() + os.EOL + os.EOL);
}
}
exports.runWithErrorAndStatusCode = runWithErrorAndStatusCode;
function run() {
const [nodePath, /* Ex: /bin/node */ scriptPath, /* /repo/common/scripts/install-run-rush.js */ rawPackageSpecifier, /* qrcode@^1.2.0 */ packageBinName, /* qrcode */ ...packageBinArgs /* [-f, myproject/lib] */] = process.argv;
if (!nodePath) {
throw new Error('Unexpected exception: could not detect node path');
}
if (path.basename(scriptPath).toLowerCase() !== 'install-run.js') {
// If install-run.js wasn't directly invoked, don't execute the rest of this function. Return control
// to the script that (presumably) imported this file
return;
}
if (process.argv.length < 4) {
console.log('Usage: install-run.js <package>@<version> <command> [args...]');
console.log('Example: install-run.js qrcode@1.2.2 qrcode https://rushjs.io');
process.exit(1);
}
runWithErrorAndStatusCode(() => {
const rushJsonFolder = findRushJsonFolder();
const rushCommonFolder = ensureAndJoinPath(rushJsonFolder, 'common');
const packageSpecifier = parsePackageSpecifier(rawPackageSpecifier);
const name = packageSpecifier.name;
const version = resolvePackageVersion(rushCommonFolder, packageSpecifier);
if (packageSpecifier.version !== version) {
console.log(`Resolved to ${name}@${version}`);
}
return installAndRun(name, version, packageBinName, packageBinArgs);
});
}
run();
//# sourceMappingURL=install-run.js.map

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,21 +0,0 @@
{
"name": "{{name}}-monorepo",
"private": true,
"version": "0.0.1",
"description": "{{name}} Monorepo",
"repository": {
"type": "git",
"url": ""
},
"license": "MIT",
"scripts": {
"build": "node common/scripts/install-run-rush.js build",
"change": "node common/scripts/install-run-rush.js change",
"checkchange": "node common/scripts/install-run-rush.js change -v",
"test": "node common/scripts/install-run-rush.js test",
"update": "node common/scripts/install-run-rush.js update",
"postinstall": "node common/scripts/install-run-rush.js install",
"add-package": "cd scripts && npm run add-package",
"upgrade-repo": "cd scripts && npm run upgrade-repo"
}
}

Просмотреть файл

@ -1,284 +0,0 @@
/**
* This is the main configuration file for Rush.
* For full documentation, please see https://rushjs.io
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",
/**
* (Required) This specifies the version of the Rush engine to be used in this repo.
* Rush's "version selector" feature ensures that the globally installed tool will
* behave like this release, regardless of which version is installed globally.
*
* The common/scripts/install-run-rush.js automation script also uses this version.
*
* NOTE: If you upgrade to a new major version of Rush, you should replace the "v5"
* path segment in the "$schema" field for all your Rush config files. This will ensure
* correct error-underlining and tab-completion for editors such as VS Code.
*/
"rushVersion": "5.6.3",
/**
* The next field selects which package manager should be installed and determines its version.
* Rush installs its own local copy of the package manager to ensure that your build process
* is fully isolated from whatever tools are present in the local environment.
*
* Specify one of: "pnpmVersion", "npmVersion", or "yarnVersion". See the Rush documentation
* for details about these alternatives.
*/
"pnpmVersion": "3.1.0",
/**
* Options that are only used when the PNPM package manager is selected
*/
"pnpmOptions": {
/**
* If true, then Rush will add the "--strict-peer-dependencies" option when invoking PNPM.
* This causes "rush install" to fail if there are unsatisfied peer dependencies, which is
* an invalid state that can cause build failures or incompatible dependency versions.
* (For historical reasons, JavaScript package managers generally do not treat this invalid
* state as an error.)
*/
"strictPeerDependencies": true
},
/**
* Specify a SemVer range to ensure developers use a NodeJS version that is appropriate
* for your repo.
*/
"nodeSupportedVersionRange": ">=8.9.4 <9.0.0 || >=10.9.0 <12.0.0",
/**
* This feature helps you to review and approve new packages before they are introduced
* to your monorepo. For example, you may be concerned about licensing, code quality,
* performance, or simply accumulating too many libraries with overlapping functionality.
* The approvals are tracked in two config files "browser-approved-packages.json"
* and "nonbrowser-approved-packages.json". See the Rush documentation for details.
*/
// "approvedPackagesPolicy": {
// /**
// * The review categories allow you to say for example "This library is approved for usage
// * in prototypes, but not in production code."
// *
// * Each project can be associated with one review category, by assigning the "reviewCategory" field
// * in the "projects" section of rush.json. The approval is then recorded in the files
// * "common/config/rush/browser-approved-packages.json" and "nonbrowser-approved-packages.json"
// * which are automatically generated during "rush update".
// *
// * Designate categories with whatever granularity is appropriate for your review process,
// * or you could just have a single category called "default".
// */
// "reviewCategories": [
// // Some example categories:
// "production", // projects that ship to production
// "tools", // non-shipping projects that are part of the developer toolchain
// "prototypes" // experiments that should mostly be ignored by the review process
// ],
//
// /**
// * A list of NPM package scopes that will be excluded from review.
// * We recommend to exclude TypeScript typings (the "@types" scope), because
// * if the underlying package was already approved, this would imply that the typings
// * are also approved.
// */
// // "ignoredNpmScopes": [ "@types" ]
// },
/**
* Large monorepos can become intimidating for newcomers if project folder paths don't follow
* a consistent and recognizable pattern. When the system allows nested folder trees,
* we've found that teams will often use subfolders to create islands that isolate
* their work from others ("shipping the org"). This hinders collaboration and code sharing.
*
* The Rush developers recommend a "category folder" model, where buildable project folders
* must always be exactly two levels below the repo root. The parent folder acts as the category.
* This provides a basic facility for grouping related projects (e.g. "apps", "libaries",
* "tools", "prototypes") while still encouraging teams to organize their projects into
* a unified taxonomy. Limiting to 2 levels seems very restrictive at first, but if you have
* 20 categories and 20 projects in each category, this scheme can easily accommodate hundreds
* of projects. In practice, you will find that the folder hierarchy needs to be rebalanced
* occasionally, but if that's painful, it's a warning sign that your development style may
* discourage refactoring. Reorganizing the categories should be an enlightening discussion
* that brings people together, and maybe also identifies poor coding practices (e.g. file
* references that reach into other project's folders without using NodeJS module resolution).
*
* The defaults are projectFolderMinDepth=1 and projectFolderMaxDepth=2.
*
* To remove these restrictions, you could set projectFolderMinDepth=1
* and set projectFolderMaxDepth to a large number.
*/
// "projectFolderMinDepth": 1,
// "projectFolderMaxDepth": 2,
/**
* Event hooks are customized script actions that Rush executes when specific events occur
*/
"eventHooks": {
/**
* The list of shell commands to run before the Rush installation starts
*/
"preRushInstall": [],
/**
* The list of shell commands to run after the Rush installation finishes
*/
"postRushInstall": [],
/**
* The list of shell commands to run before the Rush build command starts
*/
"preRushBuild": [],
/**
* The list of shell commands to run after the Rush build command finishes
*/
"postRushBuild": []
},
/**
* If you would like the version specifiers for your dependencies to be consistent, then
* uncomment this line. This is effectively similar to running "rush check" before any
* of the following commands:
*
* rush install, rush update, rush link, rush version, rush publish
*
* In some cases you may want this turned on, but need to allow certain packages to use a different
* version. In those cases, you will need to add an entry to the "allowedAlternateVersions"
* section of the common-versions.json.
*/
// "ensureConsistentVersions": true,
/**
* If you use Git as your version control system, this section has some additional
* optional features you can use.
*/
"gitPolicy": {
/**
* Work at a big company? Tired of finding Git commits at work with unprofessional Git
* emails such as "beer-lover@my-college.edu"? Rush can validate people's Git email address
* before they get started.
*
* Define a list of regular expressions describing allowable e-mail patterns for Git commits.
* They are case-insensitive anchored JavaScript RegExps. Example: ".*@example\.com"
*
* IMPORTANT: Because these are regular expressions encoded as JSON string literals,
* RegExp escapes need two backspashes, and ordinary periods should be "\\.".
*/
// "allowedEmailRegExps": [
// "[^@]+@users\\.noreply\\.github\\.com",
// "travis@example\\.org"
// ],
/**
* When Rush reports that the address is malformed, the notice can include an example
* of a recommended email. Make sure it conforms to one of the allowedEmailRegExps
* expressions.
*/
// "sampleEmail": "mrexample@users.noreply.github.com"
},
"repository": {
/**
* This setting is sometimes needed when using "rush change" with multiple Git remotes.
* It specifies the remote url for the official Git repository. If this URL is provided,
* "rush change" will use it to find the right remote to compare against.
*/
// "url": "https://github.com/microsoft/rush-example"
},
/**
* Installation variants allow you to maintain a parallel set of configuration files that can be
* used to build the entire monorepo with an alternate set of dependencies. For example, suppose
* you upgrade all your projects to use a new release of an important framework, but during a transition period
* you intend to maintain compability with the old release. In this situation, you probably want your
* CI validation to build the entire repo twice: once with the old release, and once with the new release.
*
* Rush "installation variants" correspond to sets of config files located under this folder:
*
* common/config/rush/variants/<variant_name>
*
* The variant folder can contain an alternate common-versions.json file. Its "preferredVersions" field can be used
* to select older versions of dependencies (within a loose SemVer range specified in your package.json files).
* To install a variant, run "rush install --variant <variant_name>".
*
* For more details and instructions, see this article: https://rushjs.io/pages/advanced/installation_variants/
*/
"variants": [
// {
// /**
// * The folder name for this variant.
// */
// "variantName": "old-sdk",
//
// /**
// * An informative description
// */
// "description": "Build this repo using the previous release of the SDK"
// }
],
/**
* Rush can collect anonymous telemetry about everyday developer activity such as
* success/failure of installs, builds, and other operations. You can use this to identify
* problems with your toolchain or Rush itself. THIS TELEMETRY IS NOT SHARED WITH MICROSOFT.
* It is written into JSON files in the common/temp folder. It's up to you to write scripts
* that read these JSON files and do something with them. These scripts are typically registered
* in the "eventHooks" section.
*/
// "telemetryEnabled": false,
/**
* Allows creation of hotfix changes. This feature is experimental so it is disabled by default.
*/
// "hotfixChangeEnabled": false,
/**
* (Required) This is the inventory of projects to be managed by Rush.
*
* Rush does not automatically scan for projects using wildcards, for a few reasons:
* 1. Depth-first scans are expensive, particularly when tools need to repeatedly collect the list.
* 2. On a caching CI machine, scans can accidentally pick up files left behind from a previous build.
* 3. It's useful to have a centralized inventory of all projects and their important metadata.
*/
"projects": [
{
/**
* The NPM package name of the project (must match package.json)
*/
"packageName": "{{name}}-scripts",
/**
* The path to the project folder, relative to the rush.json config file.
*/
"projectFolder": "scripts"
/**
* A flag indicating that changes to this project will be published to npm, which affects
* the Rush change and publish workflows. The default value is false.
* NOTE: "versionPolicyName" and "shouldPublish" are alternatives; you cannot specify them both.
*/
// "shouldPublish": true,
// /**
// * An optional category for usage in the "browser-approved-packages.json"
// * and "nonbrowser-approved-packages.json" files. The value must be one of the
// * strings from the "reviewCategories" defined above.
// */
// "reviewCategory": "production",
// /**
// * A list of local projects that appear as devDependencies for this project, but cannot be
// * locally linked because it would create a cyclic dependency; instead, the last published
// * version will be installed in the Common folder.
// */
// "cyclicDependencyProjects": [
// // "my-toolchain"
// ],
// /**
// * If true, then this project will be ignored by the "rush check" command.
// * The default value is false.
// */
// "skipRushCheck": false,
}
]
}

Просмотреть файл

@ -1,3 +0,0 @@
// @ts-check
const { taskPresets } = require('just-scripts');
module.exports = taskPresets.monorepo;

Просмотреть файл

@ -1,23 +0,0 @@
{
"name": "{{name}}-scripts",
"private": true,
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"add-package": "just add-package --cwd ../",
"upgrade-repo": "just upgrade-repo --cwd ../",
"build": ""
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"just-task": "^0.9.0",
"just-scripts": "^0.14.0"
},
"devDependencies": {
"just-stack-single-lib": ">=0.1.0",
"just-stack-uifabric": ">=0.1.0"
}
}

Просмотреть файл

@ -0,0 +1,4 @@
CHANGELOG.*
*.log
node_modules

Просмотреть файл

@ -0,0 +1,37 @@
{
"name": "just-stack-react",
"version": "0.2.0",
"license": "MIT",
"main": "index.js",
"dependencies": {
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.3.3",
"@types/jest": "^24.0.16",
"@types/react": "^16.8.24",
"@types/react-dom": "^16.8.5",
"acorn": "^6.0.0",
"autoprefixer": "^9.4.5",
"beachball": "^1.11.5",
"css-loader": "^2.1.0",
"file-loader": "^3.0.1",
"fork-ts-checker-webpack-plugin": "^1.2.0",
"fs-extra": "^7.0.1",
"glob": "^7.1.3",
"html-webpack-plugin": "^3.2.0",
"jest": "^24.8.0",
"jest-expect-message": "^1.0.2",
"node-sass": "^4.11.0",
"plop": "^2.4.0",
"postcss": "^7.0.13",
"postcss-loader": "^3.0.0",
"style-loader": "^0.23.1",
"ts-loader": "^5.3.3",
"tslib": "^1.9.3",
"typescript": "^3.5.3",
"webpack": "~4.29.5",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14"
}
}

Просмотреть файл

@ -0,0 +1,3 @@
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-typescript', '@babel/preset-react']
};

4
packages/just-stack-react/plop-templates/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
node_modules
lib
lib-commonjs
dist

Просмотреть файл

@ -0,0 +1,5 @@
module.exports = {
clearMocks: true,
testEnvironment: 'jsdom',
testMatch: ['<rootDir>/src/**/__tests__/**/*.[jt]s?(x)', '<rootDir>/src/**/?(*.)+(spec|test).[tj]s?(x)']
};

Просмотреть файл

@ -1,3 +1,3 @@
// @ts-check
const { taskPresets } = require('just-scripts');
module.exports = taskPresets.lib;
taskPresets.webapp();

Просмотреть файл

@ -0,0 +1,23 @@
{
"name": "{{name}}-single",
"version": "0.1.0",
"license": "MIT",
"main": "lib-commonjs/index.js",
"module": "lib/index.js",
"scripts": {
"build": "just-scripts build",
"just": "just-scripts",
"start": "just-scripts start",
"test": "just-scripts test",
"change": "npx beachball change",
"gen": "npx plop"
},
"dependencies": {
"react": "^16.8.6",
"react-dom": "^16.8.6"
},
"devDependencies": {
"just-stack-react": "^0.1.0",
"just-scripts": "^0.26.0"
}
}

Просмотреть файл

@ -0,0 +1,13 @@
import React from 'react';
export interface \{{pascalCase componentName}}Props {
// Fill in props here
}
export const \{{pascalCase componentName}} = (props: \{{pascalCase componentName}}Props) => {
return (
<div>
{/* TODO */}
</div>
);
}

Просмотреть файл

@ -0,0 +1,19 @@
module.exports = plop => {
plop.setGenerator('component', {
prompts: [
{
type: 'input',
name: 'componentName',
message: 'Name of the component (will be converted to PascalCase): '
}
],
actions: [
{
type: 'add',
templateFile: 'plop-templates/component/component.tsx.hbs',
path: 'src/components/\{{pascalCase componentName}}.tsx'
}
]
});
};

Просмотреть файл

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<div id="app"/>
</body>
</html>

Просмотреть файл

@ -0,0 +1,3 @@
import React from 'react';
export default () => <div>This is an application</div>;

Просмотреть файл

@ -0,0 +1,7 @@
import { hello } from '../helloworld';
describe('hello', () => {
it('says hello', () => {
const result = hello('world');
expect(result).toBe('hello world');
});
});

Просмотреть файл

@ -0,0 +1,3 @@
export const hello = (name: string) => {
return `hello ${name}`;
};

Просмотреть файл

@ -0,0 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('app'));

Просмотреть файл

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"jsx": "react",
"declaration": true,
"outDir": "./lib",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"typeRoots": ["node_modules/@types", "node_modules/just-stack-react/node_modules/@types"]
},
"include": ["src", "typings/*.d.ts"]
}

Просмотреть файл

@ -0,0 +1,64 @@
/// <reference types="node" />
/// <reference types="react" />
/// <reference types="react-dom" />
declare namespace NodeJS {
interface ProcessEnv {
readonly NODE_ENV: 'development' | 'production' | 'test';
readonly PUBLIC_URL: string;
}
}
declare module '*.bmp' {
const src: string;
export default src;
}
declare module '*.gif' {
const src: string;
export default src;
}
declare module '*.jpg' {
const src: string;
export default src;
}
declare module '*.jpeg' {
const src: string;
export default src;
}
declare module '*.png' {
const src: string;
export default src;
}
declare module '*.webp' {
const src: string;
export default src;
}
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
const src: string;
export default src;
}
declare module '*.module.css' {
const classes: { [key: string]: string };
export default classes;
}
declare module '*.module.scss' {
const classes: { [key: string]: string };
export default classes;
}
declare module '*.module.sass' {
const classes: { [key: string]: string };
export default classes;
}

Просмотреть файл

@ -0,0 +1,11 @@
const { webpackConfig, webpackMerge, htmlOverlay } = require('just-scripts');
module.exports = webpackMerge(
webpackConfig,
htmlOverlay({
template: 'public/index.html'
}),
{
// Here you can custom webpack configurations
}
);

Просмотреть файл

@ -0,0 +1,13 @@
const { webpackMerge, htmlOverlay, webpackServeConfig } = require('just-scripts');
module.exports = webpackMerge(
webpackServeConfig,
htmlOverlay({
template: 'public/index.html'
}),
{
// Here you can custom webpack configurations
output: {
publicPath: '/'
}
}
);

Просмотреть файл

@ -0,0 +1,12 @@
module.exports = function(plop) {
plop.setGenerator('repo:just-stack-react', {
actions: [
{
type: 'addMany',
templateFiles: ['plop-templates/**/*.*', 'plop-templates/**/.*'],
destination: '.',
force: true
}
]
});
};

Просмотреть файл

@ -1,5 +1,3 @@
CHANGELOG.*
*.log
package-deps.json
template.spec.js
jest.config.js
node_modules

Просмотреть файл

@ -1 +0,0 @@
module.exports = require('../../scripts/jest.template.config');

Просмотреть файл

@ -1,34 +1,25 @@
{
"name": "just-stack-single-lib",
"version": "0.8.7",
"just-stack": true,
"description": "Just stack for basic Node library",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/just"
},
"main": "index.js",
"keywords": [
"just-stack"
],
"author": "",
"license": "MIT",
"main": "lib-commonjs/index.js",
"module": "lib/index.js",
"scripts": {
"build": "npm test",
"test": "jest"
"build": "just-scripts build",
"just": "just-scripts",
"start": "just-scripts start",
"test": "just-scripts test",
"change": "beachball change"
},
"dependencies": {
"fs-extra": "^7.0.1",
"glob": "^7.1.3",
"jest-expect-message": "^1.0.2",
"json5": "^2.1.0",
"just-scripts-utils": "^0.8.2",
"@types/jest": "^24.0.0",
"jest": "^24.0.0",
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.3.3",
"@types/jest": "^24.0.16",
"beachball": "^1.11.5",
"jest": "^24.8.0",
"just-scripts": "^0.26.0",
"just-task": "^0.13.1",
"ts-jest": "^24.0.1",
"tslib": "^1.9.3",
"typescript": "^3.2.4"
"typescript": "^3.5.3"
}
}

Просмотреть файл

@ -0,0 +1,3 @@
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-typescript', '@babel/preset-react']
};

4
packages/just-stack-single-lib/plop-templates/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
node_modules
lib
lib-commonjs
dist

Просмотреть файл

@ -0,0 +1,5 @@
module.exports = {
clearMocks: true,
testEnvironment: 'node',
testMatch: ['<rootDir>/src/**/__tests__/**/*.[jt]s?(x)', '<rootDir>/src/**/?(*.)+(spec|test).[tj]s?(x)']
};

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше