Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[WIP] Bolt monorepo for NPM migration #3483

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6393ebc
Copy libdefs into experiments/definitions/ with the new libdef struct…
Jun 13, 2018
0bae2ea
Copy libdefs from definitions/browser into experimental/definitions (…
Jun 18, 2018
783448d
run tests against experimental folder structure
Oct 1, 2018
6957bc2
generate package.json, copy over tests
Jan 15, 2019
2eaa1a9
update definition syncer
Mar 12, 2019
30468b0
Add bolt fork package
goodmind May 19, 2019
ad575ff
Use flow-typed fork
goodmind May 20, 2019
f91b51d
Generate flowVersion for node_modules resolving
goodmind May 21, 2019
af1219b
Ignore node_modules when searching for workspaces
goodmind May 21, 2019
528d9bf
Add peer dependency generation and restrict files
goodmind May 21, 2019
ee2b59b
Add scope packages
goodmind May 24, 2019
49d9cdf
Move package name to variable
goodmind May 24, 2019
6fed28c
Remove peerDependencies
goodmind May 25, 2019
844fe96
Read tests directories for test runner
goodmind Jun 8, 2019
c2ba2d1
Add patch versions on each next libdef
goodmind Jun 8, 2019
6175c7b
Fix scoped package name for experimental structure
goodmind Jun 18, 2019
723ed56
Add TODO for experimental directory structure
goodmind Jun 18, 2019
90677f8
Add experimental tree to Git
goodmind Jun 19, 2019
8306737
Add CLI metadata to experimental tree
goodmind Jun 19, 2019
4887458
Add experimental tests directory
goodmind Jun 23, 2019
ca8ce19
Fix folder resolving
goodmind Aug 1, 2019
4f06d97
Update experimental tree
goodmind Aug 1, 2019
abb0608
Remove experimental tree
goodmind Aug 9, 2019
5d034e6
Sort definitions by Flow version
goodmind Aug 10, 2019
45f9c6f
Fix tests running for dependencies
goodmind Aug 20, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,64 @@
declare module '@babel/code-frame' {
declare export type SourceLocation = {
start: {|
line: number,
column?: number,
|},
end?: {|
line: number,
column?: number,
|},
};
declare export function codeFrameColumns(
rawLines: string,
location: SourceLocation,
options?: BabelCodeFrameOptions
): string;

declare export type BabelCodeFrameOptions = {
/**
* Syntax highlight the code as JavaScript for terminals. default: false
*/
highlightCode?: boolean,

/**
* The number of lines to show above the error. default: 2
*/
linesAbove?: number,

/**
* The number of lines to show below the error. default: 3
*/
linesBelow?: number,

/**
* Forcibly syntax highlight the code as JavaScript (for non-terminals);
* overrides highlightCode.
* default: false
*/
forceColor?: boolean,

/**
* Pass in a string to be displayed inline (if possible) next to the
* highlighted location in the code. If it can't be positioned inline,
* it will be placed above the code frame.
* default: nothing
*/
message?: string,
}

/**
* Generate errors that contain a code frame that point to source locations.
* @param rawLines Raw lines to frame
* @param lineNumber Line number (1 indexed)
* @param colNumber Column number
* @param options Additional options
* @returns Framed code
*/
declare export default function codeFrame(
rawLines: string,
lineNumber: number,
colNumber: number,
options?: BabelCodeFrameOptions
): string;
}
@@ -0,0 +1,24 @@
// @flow

import {describe, it} from 'flow-typed-test';
import codeFrame, {codeFrameColumns} from '@babel/code-frame';

const code = `
const number = 1;
var string = 'foo';
function print(name: string) {
console.log(string + name);
}
`;

it('codeFrame', () => {
codeFrame(code, 5, 22);
codeFrame(code, 5, 22, {forceColor: true});
codeFrame(code, 2, 2, {highlightCode: true});
});

it('codeFrameColumns', () => {
codeFrameColumns(code, {start: {line: 5, column: 22}});
codeFrameColumns(code, {start: {line: 5, column: 22}}, {forceColor: true});
codeFrameColumns(code, {start: {line: 2, column: 2}}, {highlightCode: true});
});
@@ -0,0 +1,66 @@
declare module '@babel/code-frame' {
declare export type SourceLocation = {
start: {|
line: number,
column?: number,
|},
end?: {|
line: number,
column?: number,
|},
...
};
declare export function codeFrameColumns(
rawLines: string,
location: SourceLocation,
options?: BabelCodeFrameOptions
): string;

declare export type BabelCodeFrameOptions = {
/**
* Syntax highlight the code as JavaScript for terminals. default: false
*/
highlightCode?: boolean,

/**
* The number of lines to show above the error. default: 2
*/
linesAbove?: number,

/**
* The number of lines to show below the error. default: 3
*/
linesBelow?: number,

/**
* Forcibly syntax highlight the code as JavaScript (for non-terminals);
* overrides highlightCode.
* default: false
*/
forceColor?: boolean,

/**
* Pass in a string to be displayed inline (if possible) next to the
* highlighted location in the code. If it can't be positioned inline,
* it will be placed above the code frame.
* default: nothing
*/
message?: string,
...
}

/**
* Generate errors that contain a code frame that point to source locations.
* @param rawLines Raw lines to frame
* @param lineNumber Line number (1 indexed)
* @param colNumber Column number
* @param options Additional options
* @returns Framed code
*/
declare export default function codeFrame(
rawLines: string,
lineNumber: number,
colNumber: number,
options?: BabelCodeFrameOptions
): string;
}
@@ -0,0 +1,32 @@
// @flow

import { describe, it } from 'flow-typed-test';
import codeFrame, { codeFrameColumns } from '@babel/code-frame';

const code = `
const number = 1;
var string = 'foo';
function print(name: string) {
console.log(string + name);
}
`;

it('codeFrame', () => {
codeFrame(code, 5, 22);
codeFrame(code, 5, 22, { forceColor: true });
codeFrame(code, 2, 2, { highlightCode: true });
});

it('codeFrameColumns', () => {
codeFrameColumns(code, { start: { line: 5, column: 22 } });
codeFrameColumns(
code,
{ start: { line: 5, column: 22 } },
{ forceColor: true }
);
codeFrameColumns(
code,
{ start: { line: 2, column: 2 } },
{ highlightCode: true }
);
});
6 changes: 3 additions & 3 deletions cli/src/commands/__tests__/install-test.js
Expand Up @@ -234,13 +234,13 @@ describe('install (command)', () => {
}),
]);
await gitInit(FAKE_CACHE_REPO_DIR),
await gitAdd(FAKE_CACHE_REPO_DIR, 'definitions');
await gitAdd(FAKE_CACHE_REPO_DIR, 'experimental');
await gitCommit(FAKE_CACHE_REPO_DIR, 'FIRST');

setCustomCacheDir(FAKE_CACHE_DIR);

const availableLibDefs = await getNpmLibDefs(
path.join(FAKE_CACHE_REPO_DIR, 'definitions'),
path.join(FAKE_CACHE_REPO_DIR, 'experimental'),
);

await installNpmLibDef(availableLibDefs[0], FLOWTYPED_DIR, false);
Expand Down Expand Up @@ -283,7 +283,7 @@ describe('install (command)', () => {
gitConfig(FAKE_CACHE_REPO_DIR, 'user.name', 'Test Author'),
gitConfig(FAKE_CACHE_REPO_DIR, 'user.email', 'test@flow-typed.org'),
]);
await gitAdd(FAKE_CACHE_REPO_DIR, 'definitions');
await gitAdd(FAKE_CACHE_REPO_DIR, 'experimental');
await gitCommit(FAKE_CACHE_REPO_DIR, 'FIRST');

setCustomCacheDir(FAKE_CACHE_DIR);
Expand Down
19 changes: 10 additions & 9 deletions cli/src/commands/runTests.js
Expand Up @@ -53,7 +53,7 @@ type TestGroup = {
* structs. Each TestGroup represents a Package/PackageVersion/FlowVersion
* directory.
*/
const basePathRegex = new RegExp('definitions/npm/(@[^/]*/)?[^/]*/?');
const basePathRegex = new RegExp('experimental/definitions/(@[^/]*/)?[^/]*/?');
async function getTestGroups(
repoDirPath,
onlyChanged: boolean = false,
Expand All @@ -75,9 +75,7 @@ async function getTestGroups(
libDefs = libDefs.filter(def => changedDefs.includes(def.pkgName));
}
return libDefs.map(libDef => {
const groupID = `${libDef.pkgName}_${libDef.pkgVersionStr}/${
libDef.flowVersionStr
}`;
const groupID = `${libDef.pkgName}_${libDef.pkgVersionStr}/${libDef.flowVersionStr}`;
return {
id: groupID,
testFilePaths: libDef.testFilePaths,
Expand Down Expand Up @@ -293,10 +291,15 @@ async function getCachedFlowBinVersions(
}

async function writeFlowConfig(repoDirPath, testDirPath, libDefPath, version) {
const basePath = path.dirname(libDefPath);
const destFlowConfigPath = path.join(testDirPath, '.flowconfig');
const pkg = path.join(basePath, 'package.json');
const deps = Object.keys(require(pkg).dependencies)
.map(key => path.join(basePath, 'node_modules', key, 'index.js'));

const flowConfigData = [
'[libs]',
...deps,
path.basename(libDefPath),
path.join(repoDirPath, '..', '__util__', 'tdd_framework.js'),
'',
Expand Down Expand Up @@ -540,9 +543,7 @@ async function runTestGroup(
);

if (lowestCapableFlowVersion !== lowestFlowVersionRan) {
console.log(`Tests for ${
testGroup.id
} ran successfully on flow ${lowestCapableFlowVersion}.
console.log(`Tests for ${testGroup.id} ran successfully on flow ${lowestCapableFlowVersion}.
Consider setting ${lowestCapableFlowVersion} as the lower bound!`);
}

Expand Down Expand Up @@ -663,10 +664,10 @@ export async function run(argv: Args): Promise<number> {

const cwd = process.cwd();
const basePath = argv.path ? String(argv.path) : cwd;
const cwdDefsNPMPath = path.join(basePath, 'definitions', 'npm');
const cwdDefsNPMPath = path.join(basePath, 'experimental', 'definitions');
let repoDirPath = (await fs.exists(cwdDefsNPMPath))
? cwdDefsNPMPath
: path.join(__dirname, '..', '..', '..', 'definitions', 'npm');
: path.join(__dirname, '..', '..', '..', 'experimental', 'definitions');

if (onlyChanged) {
console.log(
Expand Down
2 changes: 1 addition & 1 deletion cli/src/lib/cacheRepoUtils.js
Expand Up @@ -127,7 +127,7 @@ export function getCacheRepoDir() {
export async function verifyCLIVersion(): Promise<void> {
const metadataPath = path.join(
getCacheRepoDir(),
'definitions',
'experimental',
'.cli-metadata.json',
);
const metadata = JSON.parse(String(await fs.readFile(metadataPath)));
Expand Down
55 changes: 41 additions & 14 deletions cli/src/lib/libDefs.js
Expand Up @@ -152,9 +152,15 @@ export {
};

async function addLibDefs(pkgDirPath, libDefs: Array<LibDef>) {
const parsedDirItem = parseRepoDirItem(pkgDirPath);
(await parseLibDefsFromPkgDir(parsedDirItem, pkgDirPath)).forEach(libDef =>
libDefs.push(libDef),
const versionedRepoDirs = await fs.readdir(pkgDirPath);
const parsedDirItems = versionedRepoDirs
.map(dir => path.join(pkgDirPath, dir))
.map(parseRepoDirItem);
await Promise.all(
parsedDirItems.map(async parsedDirItem => {
const libdefs = await parseLibDefsFromPkgDir(parsedDirItem);
libdefs.forEach(libDef => libDefs.push(libDef));
}),
);
}

Expand Down Expand Up @@ -209,10 +215,11 @@ function parsePkgFlowDirVersion(pkgFlowDirPath): FlowVersion {
* on disk, scan the directory and generate a list of LibDefs for each
* flow-versioned definition file.
*/
async function parseLibDefsFromPkgDir(
{pkgName, pkgVersion},
pkgDirPath,
): Promise<Array<LibDef>> {
async function parseLibDefsFromPkgDir({
pkgName,
pkgVersion,
path: pkgDirPath,
}): Promise<Array<LibDef>> {
const pkgVersionStr = versionToString(pkgVersion);
const pkgDirItems = await fs.readdir(pkgDirPath);

Expand Down Expand Up @@ -251,9 +258,7 @@ async function parseLibDefsFromPkgDir(
await P.all(
flowDirs.map(async ([flowDirPath, flowVersion]) => {
const testFilePaths = [].concat(commonTestFiles);
const basePkgName =
pkgName.charAt(0) === '@' ? pkgName.split(path.sep).pop() : pkgName;
const libDefFileName = `${basePkgName}_${pkgVersionStr}.js`;
const libDefFileName = `index.js`;
let libDefFilePath;
(await fs.readdir(flowDirPath)).forEach(flowDirItem => {
const flowDirItemPath = path.join(flowDirPath, flowDirItem);
Expand All @@ -280,11 +285,25 @@ async function parseLibDefsFromPkgDir(
testFilePaths.push(flowDirItemPath);
}
} else {
const isValidTestDir =
path.basename(flowDirItemPath) === 'tests' ||
path.basename(flowDirItemPath) === 'node_modules';
if (isValidTestDir) return;
const error = 'Unexpected directory item: ' + flowDirItemPath;
throw new ValidationError(error);
}
});

(await fs.readdir(path.join(flowDirPath, 'tests'))).forEach(
testFileItem => {
const flowDirItemPath = path.join(flowDirPath, 'tests', testFileItem);
const isValidTestFile = validateTestFile(flowDirItemPath);
if (isValidTestFile) {
testFilePaths.push(flowDirItemPath);
}
},
);

if (libDefFilePath == null) {
libDefFilePath = path.join(flowDirPath, libDefFileName);
if (pkgName !== 'ERROR') {
Expand Down Expand Up @@ -326,7 +345,7 @@ export function parseRepoDirItem(dirItemPath: string) {
const item = path
.dirname(dirItemPath)
.split(path.sep)
.pop();
.splice(-2, 2)[0];
if (item.charAt(0) === '@') {
pkgName = `${item}${path.sep}${pkgName}`;
}
Expand All @@ -338,7 +357,11 @@ export function parseRepoDirItem(dirItemPath: string) {
prerel = prerel.substr(1);
}

return {pkgName, pkgVersion: {major, minor, patch, prerel}};
return {
pkgName,
pkgVersion: {major, minor, patch, prerel},
path: dirItemPath,
};
}

/**
Expand Down Expand Up @@ -415,12 +438,16 @@ function writeVerbose(stream, msg, writeNewline = true) {
* If the repo checkout does not exist or is out of date, it will be
* created/updated automatically first.
*/
const CACHE_REPO_DEFS_DIR = path.join(CACHE_REPO_DIR, 'definitions', 'npm');
const CACHE_REPO_DEFS_DIR = path.join(
CACHE_REPO_DIR,
'experimental',
'definitions',
);
export async function getCacheLibDefs(
verbose?: VerboseOutput = process.stdout,
) {
await ensureCacheRepo(verbose);
await verifyCLIVersion(path.join(CACHE_REPO_DIR, 'definitions'));
await verifyCLIVersion(path.join(CACHE_REPO_DIR, 'experimental'));
return getLibDefs(CACHE_REPO_DEFS_DIR);
}

Expand Down