Skip to content

Commit 355b4d0

Browse files
emmatownNoviny
authored andcommitted
Convert get-workspaces to TypeScript (changesets#41)
* Convert get-workspaces to TypeScript * Throw when a name field is missing and other things * Collect packages with no name field and throw one error
1 parent 61ac9ce commit 355b4d0

File tree

14 files changed

+217
-4
lines changed

14 files changed

+217
-4
lines changed

.changeset/50f184c5/changes.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"releases": [{ "name": "get-workspaces", "type": "minor" }],
3+
"dependents": [
4+
{
5+
"name": "@changesets/cli",
6+
"type": "patch",
7+
"dependencies": ["get-workspaces"]
8+
}
9+
]
10+
}

.changeset/50f184c5/changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Throw when the name field is missing in a package.json

.changeset/cb4d5155/changes.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"releases": [{ "name": "get-workspaces", "type": "patch" }],
3+
"dependents": []
4+
}

.changeset/cb4d5155/changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Convert package to TypeScript

babel.config.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ module.exports = {
55
{
66
targets: { node: 8 }
77
}
8-
],
9-
"@babel/preset-flow"
8+
]
9+
],
10+
overrides: [
11+
{ test: "**/*.ts", presets: ["@babel/preset-typescript"] },
12+
{ test: "**/*.js", presets: ["@babel/preset-flow"] }
1013
]
1114
};

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"lint": "yarn lint:eslint && yarn lint:prettier",
1212
"lint:eslint": "yarn eslint . --ext .ts,.tsx,.js",
1313
"lint:prettier": "prettier --list-different \"**/*.{js,ts,tsx}\"",
14+
"types:check": "tsc",
1415
"prettier": "prettier --write \"**/*.{js,ts,tsx}\"",
1516
"changeset": "packages/cli/bin.js",
1617
"release": "yarn build && packages/cli/bin.js release --public"
@@ -22,6 +23,8 @@
2223
"license": "MIT",
2324
"dependencies": {
2425
"@babel/runtime": "^7.4.4",
26+
"@types/fs-extra": "^5.1.0",
27+
"@types/jest": "^24.0.12",
2528
"bolt": "^0.22.1",
2629
"boxen": "^1.3.0",
2730
"chalk": "^2.1.0",
@@ -40,13 +43,15 @@
4043
"projector-spawn": "^1.0.1",
4144
"semver": "^5.4.1",
4245
"tty-table": "^2.7.0",
46+
"typescript": "^3.4.5",
4347
"uuid": "^3.3.2"
4448
},
4549
"devDependencies": {
4650
"@babel/cli": "^7.4.4",
4751
"@babel/core": "^7.0.0-0",
4852
"@babel/preset-env": "^7.4.4",
4953
"@babel/preset-flow": "^7.0.0",
54+
"@babel/preset-typescript": "^7.3.3",
5055
"babel-eslint": "^10.0.1",
5156
"dotenv": "^8.0.0",
5257
"eslint": "^5.16.0",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"private": true,
3+
"name": "yarn-workspace-base",
4+
"description": "Base yarn workspace work",
5+
"version": "1.0.0",
6+
"workspaces": [
7+
"packages/*"
8+
]
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"version": "1.0.0",
3+
"dependencies": {
4+
"pkg-b": "1.0.0"
5+
}
6+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"version": "1.0.0"
3+
}

packages/get-workspaces/src/index.test.js renamed to packages/get-workspaces/src/index.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,54 @@ describe("get-workspaces", () => {
55
it("should resolve yarn workspaces if the yarn option is passed", async () => {
66
let cwd = await getFixturePath(__dirname, "yarn-workspace-base");
77
const workspaces = await getWorkspaces({ cwd, tools: ["yarn"] });
8+
if (workspaces === null) {
9+
return expect(workspaces).not.toBeNull();
10+
}
811
expect(workspaces[0].name).toEqual("yarn-workspace-base-pkg-a");
912
expect(workspaces[1].name).toEqual("yarn-workspace-base-pkg-b");
1013
});
1114
it("should resolve yarn workspaces if the yarn option is passed and packages field is used", async () => {
1215
let cwd = await getFixturePath(__dirname, "yarn-workspace-packages");
1316
const workspaces = await getWorkspaces({ cwd, tools: ["yarn"] });
17+
if (workspaces === null) {
18+
return expect(workspaces).not.toBeNull();
19+
}
1420
expect(workspaces[0].name).toEqual("yarn-workspace-package-pkg-a");
1521
expect(workspaces[1].name).toEqual("yarn-workspace-package-pkg-b");
1622
});
1723
it("should resolve bolt workspaces if the bolt option is passed", async () => {
1824
let cwd = await getFixturePath(__dirname, "bolt-workspace");
1925
const workspaces = await getWorkspaces({ cwd, tools: ["bolt"] });
26+
if (workspaces === null) {
27+
return expect(workspaces).not.toBeNull();
28+
}
2029
expect(workspaces[0].name).toEqual("bolt-workspace-pkg-a");
2130
expect(workspaces[1].name).toEqual("bolt-workspace-pkg-b");
2231
});
2332
it("should resolve main package if root option is passed", async () => {
2433
let cwd = await getFixturePath(__dirname, "root-only");
2534
const workspaces = await getWorkspaces({ cwd, tools: ["root"] });
35+
if (workspaces === null) {
36+
return expect(workspaces).not.toBeNull();
37+
}
2638
expect(workspaces.length).toEqual(1);
39+
expect(workspaces[0].dir).toEqual(cwd);
2740
});
2841
it("should by default resolve yarn workspaces", async () => {
2942
let cwd = await getFixturePath(__dirname, "yarn-workspace-base");
3043
const workspaces = await getWorkspaces({ cwd });
44+
if (workspaces === null) {
45+
return expect(workspaces).not.toBeNull();
46+
}
3147
expect(workspaces[0].name).toEqual("yarn-workspace-base-pkg-a");
3248
expect(workspaces[1].name).toEqual("yarn-workspace-base-pkg-b");
3349
});
3450
it("should by default resolve bolt workspaces if yarn workspaces are absent", async () => {
3551
let cwd = await getFixturePath(__dirname, "bolt-workspace");
3652
const workspaces = await getWorkspaces({ cwd });
53+
if (workspaces === null) {
54+
return expect(workspaces).not.toBeNull();
55+
}
3756
expect(workspaces[0].name).toEqual("bolt-workspace-pkg-a");
3857
expect(workspaces[1].name).toEqual("bolt-workspace-pkg-b");
3958
});
@@ -42,4 +61,17 @@ describe("get-workspaces", () => {
4261
const workspaces = await getWorkspaces({ cwd });
4362
expect(workspaces).toEqual(null);
4463
});
64+
65+
it("should throw an error if a package.json is missing the name field", async () => {
66+
let cwd = await getFixturePath(__dirname, "no-name-field");
67+
try {
68+
await getWorkspaces({ cwd });
69+
} catch (err) {
70+
expect(err.message).toBe(
71+
'The following package.jsons are missing the "name" field:\npackages/pkg-a/package.json\npackages/pkg-b/package.json'
72+
);
73+
return;
74+
}
75+
expect(true).toBe(false);
76+
});
4577
});

packages/get-workspaces/src/index.js renamed to packages/get-workspaces/src/index.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ import fs from "fs-extra";
66
import path from "path";
77
import globby from "globby";
88

9-
export default async function getWorkspaces(opts) {
9+
type Options = {
10+
cwd?: string;
11+
tools?: Array<"yarn" | "bolt" | "root">;
12+
};
13+
14+
export default async function getWorkspaces(
15+
opts: Options = {}
16+
): Promise<Array<{ config: object; name: string; dir: string }> | null> {
1017
const cwd = opts.cwd || process.cwd();
1118
const tools = opts.tools || ["yarn", "bolt"]; // We also support root, but don't do it by default
1219

@@ -40,15 +47,29 @@ export default async function getWorkspaces(opts) {
4047
expandDirectories: false
4148
});
4249

50+
let pkgJsonsMissingNameField: Array<string> = [];
51+
4352
const results = await Promise.all(
4453
folders
4554
.filter(dir => fs.existsSync(path.join(dir, "package.json")))
4655
.map(async dir =>
47-
fs.readFile(path.join(dir, "package.json")).then(contents => {
56+
fs.readFile(path.join(dir, "package.json"), "utf8").then(contents => {
4857
const config = JSON.parse(contents);
58+
if (!config.name) {
59+
pkgJsonsMissingNameField.push(
60+
path.relative(cwd, path.join(dir, "package.json"))
61+
);
62+
}
4963
return { config, name: config.name, dir };
5064
})
5165
)
5266
);
67+
if (pkgJsonsMissingNameField.length !== 0) {
68+
throw new Error(
69+
`The following package.jsons are missing the "name" field:\n${pkgJsonsMissingNameField.join(
70+
"\n"
71+
)}`
72+
);
73+
}
5374
return results;
5475
}

tsconfig.json

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"compilerOptions": {
3+
/* Basic Options */
4+
"target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
5+
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
6+
// "lib": [], /* Specify library files to be included in the compilation. */
7+
// "allowJs": true, /* Allow javascript files to be compiled. */
8+
// "checkJs": true, /* Report errors in .js files. */
9+
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
10+
// "declaration": true, /* Generates corresponding '.d.ts' file. */
11+
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
12+
// "sourceMap": true, /* Generates corresponding '.map' file. */
13+
// "outFile": "./", /* Concatenate and emit output to single file. */
14+
// "outDir": "./", /* Redirect output structure to the directory. */
15+
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
16+
// "composite": true, /* Enable project compilation */
17+
// "incremental": true, /* Enable incremental compilation */
18+
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
19+
// "removeComments": true, /* Do not emit comments to output. */
20+
// "noEmit": true, /* Do not emit outputs. */
21+
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
22+
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
23+
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
24+
25+
/* Strict Type-Checking Options */
26+
"strict": true /* Enable all strict type-checking options. */,
27+
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
28+
// "strictNullChecks": true, /* Enable strict null checks. */
29+
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
30+
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
31+
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
32+
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
33+
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
34+
35+
/* Additional Checks */
36+
// "noUnusedLocals": true, /* Report errors on unused locals. */
37+
// "noUnusedParameters": true, /* Report errors on unused parameters. */
38+
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
39+
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
40+
41+
/* Module Resolution Options */
42+
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
43+
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
44+
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
45+
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
46+
// "typeRoots": [], /* List of folders to include type definitions from. */
47+
// "types": [], /* Type declaration files to be included in compilation. */
48+
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
49+
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
50+
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
51+
52+
/* Source Map Options */
53+
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
54+
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
55+
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
56+
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
57+
58+
/* Experimental Options */
59+
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
60+
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
61+
"noEmit": true
62+
}
63+
}

types/jest-fixtures.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
declare module "jest-fixtures" {
2+
// this type is technically wrong because getFixturePath can return null
3+
// but really we need jest-fixtures to throw an error when a fixture can't be found
4+
// because checking for null in every usage of these things would be ridiculous
5+
// or we could use fixturez which IMO has a better API and throws when fixtures
6+
// can't be found
7+
export function getFixturePath(dir: string, fixtureName: string): string;
8+
}

yarn.lock

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,13 @@
276276
dependencies:
277277
"@babel/helper-plugin-utils" "^7.0.0"
278278

279+
"@babel/plugin-syntax-typescript@^7.2.0":
280+
version "7.3.3"
281+
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz#a7cc3f66119a9f7ebe2de5383cce193473d65991"
282+
integrity sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag==
283+
dependencies:
284+
"@babel/helper-plugin-utils" "^7.0.0"
285+
279286
"@babel/plugin-transform-arrow-functions@^7.2.0":
280287
version "7.2.0"
281288
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550"
@@ -496,6 +503,14 @@
496503
dependencies:
497504
"@babel/helper-plugin-utils" "^7.0.0"
498505

506+
"@babel/plugin-transform-typescript@^7.3.2":
507+
version "7.4.4"
508+
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.4.tgz#93e9c3f2a546e6d3da1e9cc990e30791b807aa9f"
509+
integrity sha512-rwDvjaMTx09WC0rXGBRlYSSkEHOKRrecY6hEr3SVIPKII8DVWXtapNAfAyMC0dovuO+zYArcAuKeu3q9DNRfzA==
510+
dependencies:
511+
"@babel/helper-plugin-utils" "^7.0.0"
512+
"@babel/plugin-syntax-typescript" "^7.2.0"
513+
499514
"@babel/plugin-transform-unicode-regex@^7.4.4":
500515
version "7.4.4"
501516
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f"
@@ -564,6 +579,14 @@
564579
"@babel/helper-plugin-utils" "^7.0.0"
565580
"@babel/plugin-transform-flow-strip-types" "^7.0.0"
566581

582+
"@babel/preset-typescript@^7.3.3":
583+
version "7.3.3"
584+
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz#88669911053fa16b2b276ea2ede2ca603b3f307a"
585+
integrity sha512-mzMVuIP4lqtn4du2ynEfdO0+RYcslwrZiJHXu4MGaC1ctJiW2fyaeDrtjJGs7R/KebZ1sgowcIoWf4uRpEfKEg==
586+
dependencies:
587+
"@babel/helper-plugin-utils" "^7.0.0"
588+
"@babel/plugin-transform-typescript" "^7.3.2"
589+
567590
"@babel/runtime@^7.4.4":
568591
version "7.4.4"
569592
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d"
@@ -791,6 +814,13 @@
791814
version "3.0.0"
792815
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
793816

817+
"@types/fs-extra@^5.1.0":
818+
version "5.1.0"
819+
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1"
820+
integrity sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ==
821+
dependencies:
822+
"@types/node" "*"
823+
794824
"@types/glob@^7.1.1":
795825
version "7.1.1"
796826
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
@@ -816,6 +846,18 @@
816846
"@types/istanbul-lib-coverage" "*"
817847
"@types/istanbul-lib-report" "*"
818848

849+
"@types/jest-diff@*":
850+
version "20.0.1"
851+
resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89"
852+
integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==
853+
854+
"@types/jest@^24.0.12":
855+
version "24.0.12"
856+
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.12.tgz#0553dd0a5ac744e7dc4e8700da6d3baedbde3e8f"
857+
integrity sha512-60sjqMhat7i7XntZckcSGV8iREJyXXI6yFHZkSZvCPUeOnEJ/VP1rU/WpEWQ56mvoh8NhC+sfKAuJRTyGtCOow==
858+
dependencies:
859+
"@types/jest-diff" "*"
860+
819861
"@types/minimatch@*":
820862
version "3.0.3"
821863
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -4983,6 +5025,11 @@ typeable-promisify@^2.0.1:
49835025
dependencies:
49845026
any-promise "^1.3.0"
49855027

5028+
typescript@^3.4.5:
5029+
version "3.4.5"
5030+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99"
5031+
integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==
5032+
49865033
typewise-core@^1.2, typewise-core@^1.2.0:
49875034
version "1.2.0"
49885035
resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195"

0 commit comments

Comments
 (0)