1
0
mirror of synced 2025-11-08 12:57:47 +00:00

chore(package): update dependencies (#194)

This commit is contained in:
Jason Dreyzehner
2019-07-09 23:29:27 -04:00
committed by GitHub
parent 8eaf9636c6
commit f033e7cebc
13 changed files with 3037 additions and 5544 deletions

View File

@@ -1,5 +1,5 @@
// tslint:disable:no-console no-if-statement no-expression-statement
import execa, { ExecaStatic, Options, StdIOOption } from 'execa';
import execa, { Options } from 'execa';
import githubUsername from 'github-username';
import { join } from 'path';
import {
@@ -9,9 +9,6 @@ import {
TypescriptStarterUserOptions
} from './utils';
// TODO: await https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24209
const inherit = 'inherit' as StdIOOption;
export enum Placeholders {
email = 'YOUR_EMAIL',
name = 'YOUR_NAME',
@@ -21,7 +18,7 @@ export enum Placeholders {
// We implement these as function factories to make unit testing easier.
export const cloneRepo = (
spawner: ExecaStatic,
spawner: typeof execa,
suppressOutput = false
) => async (
repoInfo: {
@@ -49,7 +46,7 @@ export const cloneRepo = (
stdio: suppressOutput ? 'pipe' : 'inherit'
});
} catch (err) {
if (err.code === 'ENOENT') {
if (err.exitCodeName === 'ENOENT') {
throw new Error(`
Git is not installed on your PATH. Please install Git and try again.
@@ -64,7 +61,7 @@ export const cloneRepo = (
cwd: projectDir,
encoding: 'utf8',
// tslint:disable-next-line:readonly-array
stdio: ['pipe', 'pipe', inherit]
stdio: ['pipe', 'pipe', 'inherit']
});
const commitHash = revParseResult.stdout;
return { commitHash, gitHistoryDir };
@@ -84,11 +81,11 @@ export const getGithubUsername = (fetcher: any) => async (
});
};
export const getUserInfo = (spawner: ExecaStatic) => async () => {
export const getUserInfo = (spawner: typeof execa) => async () => {
const opts: Options = {
encoding: 'utf8',
// tslint:disable-next-line:readonly-array
stdio: ['pipe', 'pipe', inherit]
stdio: ['pipe', 'pipe', 'inherit']
};
try {
const nameResult = await spawner('git', ['config', 'user.name'], opts);
@@ -105,7 +102,7 @@ export const getUserInfo = (spawner: ExecaStatic) => async () => {
}
};
export const initialCommit = (spawner: ExecaStatic) => async (
export const initialCommit = (spawner: typeof execa) => async (
hash: string,
projectDir: string
): Promise<void> => {
@@ -127,7 +124,7 @@ export const initialCommit = (spawner: ExecaStatic) => async (
);
};
export const install = (spawner: ExecaStatic) => async (
export const install = (spawner: typeof execa) => async (
runner: Runner,
projectDir: string
) => {

View File

@@ -20,10 +20,10 @@ import execa from 'execa';
import globby from 'globby';
import md5File from 'md5-file';
import meow from 'meow';
import { join, normalize, relative } from 'path';
import { join, relative } from 'path';
import { cloneRepo, Placeholders, Tasks } from '../tasks';
import { typescriptStarter } from '../typescript-starter';
import { Runner } from '../utils';
import { normalizePath, Runner } from '../utils';
/**
* NOTE: many of the tests below validate file modification. The filesystem is
@@ -85,14 +85,14 @@ test('returns help/usage', async t => {
test('errors if project name collides with an existing path', async t => {
const existingDir = 'build';
const error = await t.throwsAsync(
const error = await t.throwsAsync<execa.ExecaError>(
execa(`./bin/typescript-starter`, [existingDir])
);
t.regex(error.stderr, /"build" path already exists/);
});
test('errors if project name is not in kebab-case', async t => {
const error = await t.throwsAsync(
const error = await t.throwsAsync<execa.ExecaError>(
execa(`./bin/typescript-starter`, ['name with spaces'])
);
t.regex(error.stderr, /should be in-kebab-case/);
@@ -102,7 +102,7 @@ async function hashAllTheThings(
projectName: string,
sandboxed = false
): Promise<{ readonly [filename: string]: string }> {
const projectDir = join(buildDir, projectName);
const projectDir = normalizePath(join(buildDir, projectName));
const rawFilePaths: ReadonlyArray<string> = await globby(
[projectDir, `!${projectDir}/.git`],
{
@@ -127,12 +127,9 @@ async function hashAllTheThings(
const hashes = await Promise.all(hashAll);
return hashes.reduce<{ readonly [filename: string]: string }>(
(acc, hash, i) => {
const trimmedNormalizedFilePath = normalize(
const trimmedNormalizedFilePath = normalizePath(
relative(buildDir, filePaths[i])
)
// On Windows, normalize returns "\\" as the path separator.
// Normalize with POSIX:
.replace(/\\/g, '/');
);
return {
...acc,
[trimmedNormalizedFilePath]: hash
@@ -155,9 +152,7 @@ const ignorePackageJson = (map: { readonly [file: string]: string }) =>
.filter(entry => !entry[0].includes('package.json'))
.reduce((ret, [path, hash]) => ({ ...ret, [path]: hash }), {});
test(`${
TestDirectories.one
}: parses CLI arguments, handles default options`, async t => {
test(`${TestDirectories.one}: parses CLI arguments, handles default options`, async t => {
const description = 'example description 1';
const { stdout } = await execa(
`../bin/typescript-starter`,
@@ -175,7 +170,7 @@ test(`${
t.regex(stdout, new RegExp(`Created ${TestDirectories.one} 🎉`));
const map = await hashAllTheThings(TestDirectories.one);
t.deepEqual(map, {
'test-1/.circleci/config.yml': '1d432962f0691700b337ccf0638ca626',
'test-1/.circleci/config.yml': 'd29447823209aa9a230f08af7e7bfcc7',
'test-1/.editorconfig': '44a3e6c69d9267b0f756986fd970a8f4',
'test-1/.github/CONTRIBUTING.md': '5f0dfa7fdf9bf828e3a3aa8fcaeece08',
'test-1/.github/ISSUE_TEMPLATE.md': '82d1b99b29f32d851627b317195e73d2',
@@ -198,9 +193,7 @@ test(`${
});
});
test(`${
TestDirectories.two
}: parses CLI arguments, handles all options`, async t => {
test(`${TestDirectories.two}: parses CLI arguments, handles all options`, async t => {
const description = 'example description 2';
const { stdout } = await execa(
`../bin/typescript-starter`,
@@ -222,7 +215,7 @@ test(`${
t.regex(stdout, new RegExp(`Created ${TestDirectories.two} 🎉`));
const map = await hashAllTheThings(TestDirectories.two);
t.deepEqual(map, {
'test-2/.circleci/config.yml': '1d432962f0691700b337ccf0638ca626',
'test-2/.circleci/config.yml': 'd29447823209aa9a230f08af7e7bfcc7',
'test-2/.editorconfig': '44a3e6c69d9267b0f756986fd970a8f4',
'test-2/.github/CONTRIBUTING.md': '5f0dfa7fdf9bf828e3a3aa8fcaeece08',
'test-2/.github/ISSUE_TEMPLATE.md': '82d1b99b29f32d851627b317195e73d2',
@@ -238,7 +231,7 @@ test(`${
'test-2/src/index.ts': 'fbc67c2cbf3a7d37e4e02583bf06eec9',
'test-2/src/lib/async.spec.ts': '1f51a721fffe53832fb289429baba971',
'test-2/src/lib/async.ts': '9012c267bb25fa98ad2561929de3d4e2',
'test-2/src/lib/hash.spec.ts': '1644d8e40a8812a63f79db318973bb82',
'test-2/src/lib/hash.spec.ts': '11589e1960ddd75e7597c9de6854cd08',
'test-2/src/lib/hash.ts': 'a4c552897f25da5963f410e375264bd1',
'test-2/src/lib/number.spec.ts': '6a9a00630b10e7d57a79678c74a0e4df',
'test-2/src/lib/number.ts': '43756f90e6ac0b1c4ee6c81d8ab969c7',
@@ -256,10 +249,9 @@ const ms = (milliseconds: number) =>
new Promise<void>(resolve => setTimeout(resolve, milliseconds));
async function testInteractive(
t: ExecutionContext<{}>,
projectName: string,
entry: ReadonlyArray<string | ReadonlyArray<string>>
): Promise<execa.ExecaReturns> {
): Promise<execa.ExecaReturnValue<string>> {
const typeDefs = entry[3] !== '';
const proc = execa(`../bin/typescript-starter`, ['--no-install'], {
cwd: buildDir,
@@ -270,64 +262,33 @@ async function testInteractive(
// https://nodejs.org/api/process.html#process_process_stdin
// proc.stdin.setEncoding('utf8');
// tslint:disable-next-line:prefer-const no-let
let buffer = '';
const checkBuffer = (regex: RegExp) => t.regex(buffer, regex);
const type = (input: string) => proc.stdin.write(input);
const clearBuffer = () => (buffer = '');
proc.stdout.on('data', (chunk: Buffer) => {
buffer += chunk.toString();
});
// wait for first chunk to be emitted
await new Promise(resolve => {
proc.stdout.once('data', resolve);
});
await ms(200);
checkBuffer(
new RegExp(`typescript-starter[\\s\\S]*Enter the new package name`)
);
clearBuffer();
type(`${projectName}${enter}`);
await ms(200);
checkBuffer(new RegExp(`${projectName}[\\s\\S]*What are you making?`));
clearBuffer();
type(`${entry[0][0]}${enter}`);
await ms(200);
checkBuffer(
new RegExp(`${entry[0][1]}[\\s\\S]*Enter the package description`)
);
clearBuffer();
type(`${entry[1]}${enter}`);
await ms(200);
checkBuffer(new RegExp(`${entry[1]}[\\s\\S]*npm or yarn\\?`));
clearBuffer();
type(`${entry[2][0]}${enter}`);
await ms(200);
const search = `\\? ${entry[2][1]}`;
const exp = typeDefs
? new RegExp(`${search}`) // should match
: new RegExp(`(?!${search})`); // should not match
checkBuffer(exp);
// tslint:disable-next-line:no-if-statement
if (typeDefs) {
clearBuffer();
type(`${entry[3][0]}${enter}`);
await ms(200);
checkBuffer(new RegExp(`${entry[3][1]}[\\s\\S]*More fun stuff`));
}
clearBuffer();
type(`${entry[4][0]}${enter}`);
await ms(200);
checkBuffer(new RegExp(`${entry[4][1]}`));
return proc;
}
test(`${
TestDirectories.three
}: interactive mode: javascript library`, async t => {
t.plan(8);
const proc = await testInteractive(t, `${TestDirectories.three}`, [
test(`${TestDirectories.three}: interactive mode: javascript library`, async t => {
const proc = await testInteractive(`${TestDirectories.three}`, [
[`${down}${up}${down}`, `Javascript library`],
`integration test 3 description`,
[`${down}${up}${down}${enter}`, `yarn`],
@@ -337,7 +298,7 @@ test(`${
await proc;
const map = await hashAllTheThings(TestDirectories.three);
t.deepEqual(map, {
'test-3/.circleci/config.yml': '1d432962f0691700b337ccf0638ca626',
'test-3/.circleci/config.yml': 'd29447823209aa9a230f08af7e7bfcc7',
'test-3/.editorconfig': '44a3e6c69d9267b0f756986fd970a8f4',
'test-3/.github/CONTRIBUTING.md': '5f0dfa7fdf9bf828e3a3aa8fcaeece08',
'test-3/.github/ISSUE_TEMPLATE.md': '82d1b99b29f32d851627b317195e73d2',
@@ -353,7 +314,7 @@ test(`${
'test-3/src/index.ts': 'fbc67c2cbf3a7d37e4e02583bf06eec9',
'test-3/src/lib/async.spec.ts': '1f51a721fffe53832fb289429baba971',
'test-3/src/lib/async.ts': '9012c267bb25fa98ad2561929de3d4e2',
'test-3/src/lib/hash.spec.ts': '1644d8e40a8812a63f79db318973bb82',
'test-3/src/lib/hash.spec.ts': '11589e1960ddd75e7597c9de6854cd08',
'test-3/src/lib/hash.ts': 'a4c552897f25da5963f410e375264bd1',
'test-3/src/lib/number.spec.ts': '6a9a00630b10e7d57a79678c74a0e4df',
'test-3/src/lib/number.ts': '43756f90e6ac0b1c4ee6c81d8ab969c7',
@@ -364,11 +325,8 @@ test(`${
});
});
test(`${
TestDirectories.four
}: interactive mode: node.js application`, async t => {
t.plan(7);
const proc = await testInteractive(t, `${TestDirectories.four}`, [
test(`${TestDirectories.four}: interactive mode: node.js application`, async t => {
const proc = await testInteractive(`${TestDirectories.four}`, [
[`${down}${up}`, `Node.js application`],
`integration test 4 description`,
[`${down}${up}${enter}`, `npm`],
@@ -378,7 +336,7 @@ test(`${
await proc;
const map = await hashAllTheThings(TestDirectories.four);
t.deepEqual(map, {
'test-4/.circleci/config.yml': '1d432962f0691700b337ccf0638ca626',
'test-4/.circleci/config.yml': 'd29447823209aa9a230f08af7e7bfcc7',
'test-4/.editorconfig': '44a3e6c69d9267b0f756986fd970a8f4',
'test-4/.github/CONTRIBUTING.md': '5f0dfa7fdf9bf828e3a3aa8fcaeece08',
'test-4/.github/ISSUE_TEMPLATE.md': '82d1b99b29f32d851627b317195e73d2',
@@ -394,7 +352,7 @@ test(`${
'test-4/src/index.ts': 'fbc67c2cbf3a7d37e4e02583bf06eec9',
'test-4/src/lib/async.spec.ts': '1f51a721fffe53832fb289429baba971',
'test-4/src/lib/async.ts': '9012c267bb25fa98ad2561929de3d4e2',
'test-4/src/lib/hash.spec.ts': '1644d8e40a8812a63f79db318973bb82',
'test-4/src/lib/hash.spec.ts': '11589e1960ddd75e7597c9de6854cd08',
'test-4/src/lib/hash.ts': 'a4c552897f25da5963f410e375264bd1',
'test-4/src/lib/number.spec.ts': '6a9a00630b10e7d57a79678c74a0e4df',
'test-4/src/lib/number.ts': '43756f90e6ac0b1c4ee6c81d8ab969c7',
@@ -436,9 +394,7 @@ const silenceConsole = (console: any) => {
};
};
test(`${
TestDirectories.five
}: Sandboxed: npm install, initial commit`, async t => {
test(`${TestDirectories.five}: Sandboxed: npm install, initial commit`, async t => {
t.plan(3);
const options = {
...sandboxOptions,
@@ -468,7 +424,7 @@ test(`${
'test-5/.gitignore': '892227b7f662b74410e9bf6fb2ae887f',
'test-5/.npmignore': '49c9375c9a1b4a1b74076f62379b0297',
'test-5/.prettierignore': '1da1ce4fdb868f0939608fafd38f9683',
'test-5/LICENSE': '8786d80048d9c837477dc3b807aaf598',
'test-5/LICENSE': '317693126d229a3cdd19725a624a56fc',
'test-5/README.md': '8fc7ecb21d7d47289e4b2469eea4db39',
'test-5/src/index.ts': '5025093b4dc30524d349fd1cc465ed30',
'test-5/src/lib/number.spec.ts': '6a9a00630b10e7d57a79678c74a0e4df',
@@ -503,7 +459,7 @@ test(`${TestDirectories.six}: Sandboxed: yarn, no initial commit`, async t => {
await typescriptStarter(options, sandboxTasks(t, false, true));
const map = await hashAllTheThings(TestDirectories.six, true);
t.deepEqual(ignorePackageJson(map), {
'test-6/.circleci/config.yml': '1d432962f0691700b337ccf0638ca626',
'test-6/.circleci/config.yml': 'd29447823209aa9a230f08af7e7bfcc7',
'test-6/.editorconfig': '44a3e6c69d9267b0f756986fd970a8f4',
'test-6/.github/CONTRIBUTING.md': '5f0dfa7fdf9bf828e3a3aa8fcaeece08',
'test-6/.github/ISSUE_TEMPLATE.md': '82d1b99b29f32d851627b317195e73d2',
@@ -512,17 +468,17 @@ test(`${TestDirectories.six}: Sandboxed: yarn, no initial commit`, async t => {
'test-6/.gitignore': 'af817565c661f1b15514584c8ea9e469',
'test-6/.npmignore': '49c9375c9a1b4a1b74076f62379b0297',
'test-6/.prettierignore': '1da1ce4fdb868f0939608fafd38f9683',
'test-6/.travis.yml': 'e7a7503bc36dc0881fffbf1916b3fa56',
'test-6/.travis.yml': 'b56cf7194d8ff58d6cf51c34b0c645e0',
'test-6/.vscode/debug-ts.js': '23eb6ab10faaa25a95f5bd3325d0455c',
'test-6/.vscode/launch.json': '669e4d1dda91c781177c6adae7aa7e00',
'test-6/.vscode/settings.json': '10c634c5fef6ecd298b6e41bf159f2cc',
'test-6/LICENSE': '1f08fdd25d16c4ee8d5233b9cb7f6051',
'test-6/LICENSE': '03ffa741a4f7e356b69353efa4937d2b',
'test-6/README.md': 'd809bcbf240f44b51b575a3d49936232',
'test-6/appveyor.yml': '56b1771c13e61307f917782f8feba0dd',
'test-6/appveyor.yml': '27c787d8e288f89c71357b1ac32b42e8',
'test-6/src/index.ts': 'fbc67c2cbf3a7d37e4e02583bf06eec9',
'test-6/src/lib/async.spec.ts': '1f51a721fffe53832fb289429baba971',
'test-6/src/lib/async.ts': '9012c267bb25fa98ad2561929de3d4e2',
'test-6/src/lib/hash.spec.ts': '1644d8e40a8812a63f79db318973bb82',
'test-6/src/lib/hash.spec.ts': '11589e1960ddd75e7597c9de6854cd08',
'test-6/src/lib/hash.ts': 'a4c552897f25da5963f410e375264bd1',
'test-6/src/lib/number.spec.ts': '6a9a00630b10e7d57a79678c74a0e4df',
'test-6/src/lib/number.ts': '43756f90e6ac0b1c4ee6c81d8ab969c7',

View File

@@ -1,6 +1,6 @@
// tslint:disable:no-expression-statement
import test from 'ava';
import { ExecaStatic } from 'execa';
import execa from 'execa';
import meow from 'meow';
import nock from 'nock';
import { checkArgs } from '../args';
@@ -60,7 +60,7 @@ test('errors if update-notifier fails', async t => {
.get('/typescript-starter')
.reply(404, {});
const error = await t.throwsAsync(checkArgs);
t.regex(error.message, /doesn\'t exist/);
t.regex(error.message, /could not be found/);
});
test('checkArgs returns the right options', async t => {
@@ -130,17 +130,19 @@ test('small ascii art shows if stdout has 74-84 columns', async t => {
t.regex(jumbo, new RegExp(snippet));
});
const mockErr = (code?: string | number) =>
const mockErr = (code: number = 1, name: string = 'ERR') =>
((() => {
const err = new Error();
const err: any = new Error();
// tslint:disable-next-line:no-object-mutation
(err as any).code = code;
err.exitCode = code;
// tslint:disable-next-line:no-object-mutation
err.exitCodeName = name;
throw err;
}) as any) as ExecaStatic;
}) as any) as typeof execa;
test('cloneRepo: errors when Git is not installed on PATH', async t => {
const error = await t.throwsAsync(
cloneRepo(mockErr('ENOENT'))({ repo: 'r', branch: '.' }, 'd', 'p')
cloneRepo(mockErr(1, 'ENOENT'))({ repo: 'r', branch: '.' }, 'd', 'p')
);
t.regex(error.message, /Git is not installed on your PATH/);
});
@@ -158,7 +160,7 @@ test('cloneRepo: throws when rev-parse fails', async t => {
const mock = ((async () => {
calls++;
return calls === 1 ? {} : (mockErr(128) as any)();
}) as any) as ExecaStatic;
}) as any) as typeof execa;
const error = await t.throwsAsync(
cloneRepo(mock)({ repo: 'r', branch: 'b' }, 'd', 'p')
);
@@ -204,7 +206,7 @@ test('getUserInfo: returns results properly', async t => {
return {
stdout: 'result'
};
}) as any) as ExecaStatic;
}) as any) as typeof execa;
const result = await getUserInfo(mock)();
t.deepEqual(result, {
gitEmail: 'result',
@@ -213,24 +215,24 @@ test('getUserInfo: returns results properly', async t => {
});
test('initialCommit: throws generated errors', async t => {
const error = await t.throwsAsync(
const error = await t.throwsAsync<execa.ExecaError>(
initialCommit(mockErr(1))('deadbeef', 'fail')
);
t.is(error.code, 1);
t.is(error.exitCode, 1);
});
test('initialCommit: spawns 3 times', async t => {
t.plan(4);
const mock = ((async () => {
t.pass();
}) as any) as ExecaStatic;
}) as any) as typeof execa;
await t.notThrowsAsync(initialCommit(mock)('commit', 'dir'));
});
test('install: uses the correct runner', async t => {
const mock = ((async (runner: Runner) => {
runner === Runner.Yarn ? t.pass() : t.fail();
}) as any) as ExecaStatic;
}) as any) as typeof execa;
await install(mock)(Runner.Yarn, 'pass');
});

View File

@@ -6,7 +6,7 @@ import ora from 'ora';
import { join } from 'path';
import replace from 'replace-in-file';
import { Placeholders, Tasks } from './tasks';
import { Runner, TypescriptStarterOptions } from './utils';
import { normalizePath, Runner, TypescriptStarterOptions } from './utils';
export async function typescriptStarter(
{
@@ -37,7 +37,7 @@ export async function typescriptStarter(
workingDirectory,
projectName
);
await del([gitHistoryDir]);
await del([normalizePath(gitHistoryDir)]);
console.log(`
${chalk.dim(`Cloned at commit: ${commitHash}`)}
`);
@@ -53,7 +53,6 @@ export async function typescriptStarter(
'gh-pages',
'npm-run-all',
'npm-scripts-info',
'nsp',
'nyc',
'opn-cli',
'prettier',
@@ -129,34 +128,34 @@ export async function typescriptStarter(
await replace({
files: join(projectPath, 'LICENSE'),
from: '2017',
to: new Date().getUTCFullYear()
to: new Date().getUTCFullYear().toString()
});
spinnerLicense.succeed();
const spinnerDelete = ora('Deleting unnecessary files').start();
await del([
join(projectPath, 'CHANGELOG.md'),
join(projectPath, 'README.md'),
join(projectPath, 'package-lock.json'),
join(projectPath, 'bin'),
join(projectPath, 'src', 'cli'),
join(projectPath, 'src', 'types', 'cli.d.ts')
normalizePath(join(projectPath, 'CHANGELOG.md')),
normalizePath(join(projectPath, 'README.md')),
normalizePath(join(projectPath, 'package-lock.json')),
normalizePath(join(projectPath, 'bin')),
normalizePath(join(projectPath, 'src', 'cli')),
normalizePath(join(projectPath, 'src', 'types', 'cli.d.ts'))
]);
if (!appveyor) {
del([join(projectPath, 'appveyor.yml')]);
del([normalizePath(join(projectPath, 'appveyor.yml'))]);
}
if (!circleci) {
del([join(projectPath, '.circleci')]);
del([normalizePath(join(projectPath, '.circleci'))]);
}
if (!travis) {
del([join(projectPath, '.travis.yml')]);
del([normalizePath(join(projectPath, '.travis.yml'))]);
}
if (!editorconfig) {
del([join(projectPath, '.editorconfig')]);
del([normalizePath(join(projectPath, '.editorconfig'))]);
}
if (!vscode) {
del([join(projectPath, '.vscode')]);
del([normalizePath(join(projectPath, '.vscode'))]);
}
spinnerDelete.succeed();
@@ -225,10 +224,10 @@ export async function typescriptStarter(
to: ''
});
await del([
join(projectPath, 'src', 'lib', 'hash.ts'),
join(projectPath, 'src', 'lib', 'hash.spec.ts'),
join(projectPath, 'src', 'lib', 'async.ts'),
join(projectPath, 'src', 'lib', 'async.spec.ts')
normalizePath(join(projectPath, 'src', 'lib', 'hash.ts')),
normalizePath(join(projectPath, 'src', 'lib', 'hash.spec.ts')),
normalizePath(join(projectPath, 'src', 'lib', 'async.ts')),
normalizePath(join(projectPath, 'src', 'lib', 'async.spec.ts'))
]);
spinnerNode.succeed();
}

View File

@@ -1,6 +1,7 @@
import chalk from 'chalk';
import { existsSync } from 'fs';
import gradient from 'gradient-string';
import { normalize } from 'path';
import validateNpmPackageName from 'validate-npm-package-name';
export enum Runner {
Npm = 'npm',
@@ -90,3 +91,10 @@ _ _ _ _ _
? chalk.bold(gradient.mind(asciiSmaller))
: `\n${chalk.cyan.bold.underline('typescript-starter')}\n`;
}
/**
* On Windows, normalize returns "\\" as the path separator.
* This method normalizes with POSIX.
*/
export const normalizePath = (path: string) =>
normalize(path).replace(/\\/g, '/');

View File

@@ -1,18 +1,13 @@
// tslint:disable:no-expression-statement no-object-mutation
import test, { Macro } from 'ava';
import test from 'ava';
import { sha256, sha256Native } from './hash';
const hash: Macro = (t, input: string, expected: string) => {
t.is(sha256(input), expected);
t.is(sha256Native(input), expected);
};
hash.title = (providedTitle: string, input: string, expected: string) =>
`${providedTitle}: ${input} => ${expected}`;
test(
'sha256',
hash,
(t, input: string, expected: string) => {
t.is(sha256(input), expected);
t.is(sha256Native(input), expected);
},
'test',
'9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
);